![]() |
|
[rant] C++0x is ...so simple. |
ImLeftFooted
Member #3,935
October 2003
![]() |
I believe the primary benefit of move semantics is for very large classes. class This{ typedef char[2048] ThisStr; ThisStr strs[2048]; }; Imagine throwing that into swap and performing 3 copies! As I understand, with move semantics a swap can be performed in a static amount of time. |
anonymous
Member #8025
November 2006
|
Dustin Dettmer said: I believe the primary benefit of move semantics is for very large classes. But how? I don't see how you could move an array (the contents of the array may be movable - you gain nothing from moving a char, though -, and there will apparently be a standard algorithm for moving them). axilmar said: By the way, I wrote the above in order to test moving. The second loop prints nothing, as expected, because the input is emptied above. Major sh1t is going to hit the fan with this... And I say this sh1t is much less of a hassle than dangling pointers. As far as standard libraries are concerned, it is going to move only those things that nobody is going to miss (as move semantics are supposed to be used), such as when swapping things or in places like vector reallocation. The concern about SC++L giving you problems is 99.9% groundless. Quote: C++0x has one big positive thing: lambdas. Extremely extremely extremely useful, and C++0x worths the trouble for lambdas alone. Indeed. Unfortunately it seems GCC doesn't have lambdas and range-for yet. |
X-G
Member #856
December 2000
![]() |
anonymous said: But how? I don't see how you could move an array Well, for instance, look at a std::vector. Right now, you cannot move a vector; you can only copy them. Copying an array of objects is a potentially very painful process, especially if it consists of objects with nontrivial copy semantisc of their own. By contrast, the move semantics of std::vector is just assigning a pointer and a size counter (or two). -- |
bamccaig
Member #7,536
July 2006
![]() |
axilmar said: void haha(vector<int> &v) { vector<int> v1 = move(v); } ... By the way, I wrote the above in order to test moving. The second loop prints nothing, as expected, because the input is emptied above. Major sh1t is going to hit the fan with this... Yes, if you write bad code bad things will happen. You shouldn't be using std::move on an lvalue reference though so it's your own fault. Move semantics are something that won't stand out to the average programmer. Unless you intend to use them, you don't even need to know they exist (and many probably won't). The ones that do know should understand them before using them so this shouldn't happen much. If it does, hold those people accountable liable, just like you would for deleting a heap object that they don't own. anonymous said: Unfortunately it seems GCC doesn't have lambdas and range-for yet.
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
anonymous
Member #8025
November 2006
|
X-G said: Well, for instance, look at a std::vector. Right now, you cannot move a vector; you can only copy them. Copying an array of objects is a potentially very painful process, especially if it consists of objects with nontrivial copy semantisc of their own. By contrast, the move semantics of std::vector is just assigning a pointer and a size counter (or two). I can see that. But I don't see how you can move a char[2048]. It is not a pointer, it is something that actually sits tight within the class. |
X-G
Member #856
December 2000
![]() |
Correct, but neither do you lose anything; copy semantics are already optimal. However, you can save significant amounts if you ever find yourself with an object like that dynamically allocated in the free store ("heap"), under the right circumstances. -- |
anonymous
Member #8025
November 2006
|
Coming back to the earlier example: 1//X class from previous posts
2class Y
3{
4 X x;
5public:
6 Y(): x(10) {}
7 X&& get() { return x; }
8};
9
10int main()
11{
12 Y y;
13 X x = y.get(); //this uses move constructor
14 x.print(); //10
15 y.get().print(); //NULL
16}
bamccaig said: I could be wrong, but I don't think that's valid. x is an lvalue. The only way to make it work is to wrap x in std::move or something similar to explicitly change it to an rvalue. Which would be wrong. It seems that this is still valid (see last line): Quote: The && indicates an "rvalue reference". An rvalue reference can bind to either an rvalue or an lvalue: X a; X f(); X& r1 = a; // bind r1 to a (an lvalue) X& r2 = f(); // error: f() is an rvalue; can't bind X&& rr1 = f(); // fine: bind rr1 to temporary X&& rr2 = a; // also fine: bind rr2 to a (an lvalue)
So one should be careful with returning &&. (I would have been more worried if returning by value allowed move construction here, but it seems existing rules about when copy construction can and cannot be elided kick in.) |
bamccaig
Member #7,536
July 2006
![]() |
anonymous said: Coming back to the earlier example... GCC (mainline revision 150667 on amd64 Linux) doesn't seem to agree with that code. 1#ifndef MAIN_HPP
2 #define MAIN_HPP
3
4 #include <cstdlib>
5 #include <iostream>
6 #include <utility>
7
8int main(int, char * []);
9
10#endif
1#include <main.hpp>
2
3class X
4{
5 int * p;
6public:
7 X(void):
8 p(0)
9 {
10 std::cout << "X(void)\n";
11 }
12
13 X(int n):
14 p(new int(n))
15 {
16 std::cout << "X(int)\n";
17 }
18
19 X(const X &) = delete;
20
21 X(X && x):
22 p(x.p)
23 {
24 x.p = 0;
25 std::cout << "X(X && x)\n";
26 }
27
28 X & operator=(const X &) = delete;
29
30 X & operator=(X && other)
31 {
32 if(this != &other)
33 {
34 delete p;
35 p = other.p;
36 other.p = 0;
37 }
38
39 std::cout << "operator=(X &&)\n";
40
41 return *this;
42 }
43
44 ~X(void)
45 {
46 delete p;
47 std::cout << "~X(void)\n";
48 }
49
50 void print(void) const
51 {
52 if(p)
53 {
54 std::cout << *p << '\n';
55 }
56 else
57 {
58 std::cout << "NULL\n";
59 }
60 }
61};
62
63class Y
64{
65 X x;
66
67public:
68 Y(void):
69 x(10)
70 {
71 }
72
73 X && get(void)
74 {
75 return x; 76 }
77};
78
79int main(int argc, char * argv[])
80{
81 Y y;
82 X x = y.get();
83
84 //this uses move constructor
85 x.print(); //10
86 y.get().print(); //NULL
87
88 return EXIT_SUCCESS;
89}
[bamccaig@sephiroth cpp-rvalue-safety-check2]$ make if [ ! -d obj ]; then \ mkdir -p obj; \ fi; g++-r150667 -c -Iinclude -std=c++0x -o obj/main.o src/main.cpp src/main.cpp: In member function ‘X&& Y::get()’: src/main.cpp:75:16: error: invalid initialization of reference of type ‘X&&’ from expression of type ‘X’ make: *** [obj/main.o] Error 1 [bamccaig@sephiroth cpp-rvalue-safety-check2]$ Note line 75. x would need to be cast to an rvalue, for example, with std::move, making the decision explicit and punishable by death. GCC (mainline revision 150667 on amd64 Linux) doesn't seem to agree with that code either. Are you sure the source is correct? 1#ifndef MAIN_HPP
2 #define MAIN_HPP
3
4 #include <cstdlib>
5 #include <iostream>
6 #include <utility>
7
8int main(int, char * []);
9
10#endif
1#include <main.hpp>
2
3int main(int argc, char * argv[])
4{
5 int a;
6 int f();
7 int& r1 = a; // bind r1 to a (an lvalue)
8 //int& r2 = f(); // error: f() is an rvalue; can't bind
9
10 int&& rr1 = f(); // fine: bind rr1 to temporary
11 int&& rr2 = a; // also fine: bind rr2 to a (an lvalue) ***
12
13 return EXIT_SUCCESS;
14}
[bamccaig@sephiroth cpp-rvalue-safety-check]$ make if [ ! -d obj ]; then \ mkdir -p obj; \ fi; g++-r150667 -c -Iinclude -std=c++0x -o obj/main.o src/main.cpp src/main.cpp: In function ‘int main(int, char**)’: src/main.cpp:11:17: error: invalid initialization of reference of type ‘int&&’ from expression of type ‘int’ make: *** [obj/main.o] Error 1 [bamccaig@sephiroth cpp-rvalue-safety-check]$ Note that line 11 is in fact not fine. Note: I realize that in both instances include/main.hpp serves little to no purpose. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
axilmar
Member #1,204
April 2001
|
anonymous said: The concern about SC++L giving you problems is 99.9% groundless. It's not. Many programmers try to optimize their programs in any place they can. Imagine if they learn that they can speed up their programs by moving things, instead of copying them! moving things around that much is the definitive recipie for trouble!!! bamccaig said: Yes, if you write bad code bad things will happen. The point of computers and computer languages is to do reliably what humans do unreliably. If a programming language does not stop me from doing the wrong things, then the programming language is not that good. |
Thomas Fjellstrom
Member #476
June 2000
![]() |
If you keep doing wrong things, you're not that good*.
-- |
anonymous
Member #8025
November 2006
|
bamccaig said: GCC (mainline revision 150667 on amd64 Linux) doesn't seem to agree with that code. Ok, sorry for the confusion. This seems to be some recent change in the rules and the FAQ might be out of date (hello Stroustrup!!!). In any case this is an important change that improves safety significantly. It's hard to get a very good picture before the whole thing is finalized and out-of-date tutorials pushed to the background. axilmar said: Imagine if they learn that they can speed up their programs by moving things, instead of copying them! moving things around that much is the definitive recipie for trouble!!! I have always found that the following is good for optimizing memory usage: vector<X*> v; //create the objects while (whatever) { X* x = new X; v.push_back(x); delete x; //saves memory and avoids memory leaks } ...
Could this hurt me? |
SiegeLord
Member #7,827
October 2006
![]() |
Thomas Fjellstrom said: and should be fired. So he's fired... who gets to fix the broken code he wrote? In the end, someone has to, and that person surely does not appreciate more pitfalls added to the language. You can do all your best to make your code safe, but if you are working with 20 other people of perhaps inferior discipline, what do you do? Have them all be fired? Who writes the code then? More features added to C++ mean less people known how to use all of it properly, therefore less people will be able to write good code (using all the features of the language) or understand other people's code (if the subsets of the language people use are not overlapping). So, the solution is either for everyone to learn C++ (uneconomical, as learning the language = not developing and thus not earning money), or restrict the development of the program to some common subset (probably impossible in all situations, plus C++ guru's feel restricted). So... there is no viable solution for this issue. C++ is fine if you develop alone... not so much when you develop with other people. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
X-G
Member #856
December 2000
![]() |
SiegeLord said: So, the solution is either for everyone to learn C++ (uneconomical, as learning the language = not developing and thus not earning money) ... so you don't think C++ programmers need to actually know C++? I'm sorry, but that's incredibly idiotic. It's not that difficult of a language to learn, anyway. Quote: C++ is fine if you develop alone... not so much when you develop with other people.
Yes, that's why no major, extremely successful piece of software was ever written in C++. -- |
SiegeLord
Member #7,827
October 2006
![]() |
Replace C++ by C++0x in my post. X-G said: It's not that difficult of a language to learn, anyway. A matter of opinion, don't you think? You yourself might be smart enough to learn it, what about your coworkers? I clearly see that the Programming Questions part of allegro.cc has plenty of C++ questions. Are you saying that you are guaranteed never to work with one of such people in your company? Quote: Yes, that's why no major, extremely successful piece of software was ever written in C++. Well, if there is no problem with the language (one of the two solutions I posted have been implemented) then there is no problem. But how are you going to implement those two solutions when C++0x arrives? You either have to re-train everyone to know the new features, or forbid using the new features altogether. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
X-G
Member #856
December 2000
![]() |
SiegeLord said: You yourself might be smart enough to learn it, what about your coworkers? My coworkers are just as good as I, or in some cases much better. Those that can't handle C++ don't stay for long. Quote: You either have to re-train everyone to know the new features Any company -- or indeed, programmer! -- that does not keep up with modern technology is doomed to fail regardless, and I wouldn't have it any other way. Stagnation ruins a lot of things. You must always continue to adapt and improve -- it's a Red Queen's game out there. -- |
SiegeLord
Member #7,827
October 2006
![]() |
One thing I forgot, what about external libraries? Can you vouch for those people too? Or do you never use external libraries? And good for you and your coworkers, not everyone has such good surroundings as you do. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
X-G
Member #856
December 2000
![]() |
You're right, they don't -- and they should blame their coworkers, not their tools. I reiterate: C++ is not a difficult language to learn. I am constantly amazed by people struggling to comprehend the simplest of concepts. -- |
gnolam
Member #2,030
March 2002
![]() |
anonymous said: vector<X*> v; //create the objects while (whatever) { X* x = new X; v.push_back(x); delete x; //saves memory and avoids memory leaks } ...
Could this hurt me? Err... it should. The pointer pushed back into v now points to invalid memory... -- |
bamccaig
Member #7,536
July 2006
![]() |
I was hoping that was sarcasm... -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
anonymous
Member #8025
November 2006
|
I suppose that was to show that there is a difference between honest human error and outright cluelessness. However, axilmar may have a point, even though IMO he hasn't put it quite clearly. (Demonstrating some misunderstanding of the topic and somewhat dogmatic fear of moving things in general.) Suppose we have a following function. void foo(X&& x) { a(x); ... b(x); ... c(std::move(x)); } As we know x comes to us from a temporary (assuming that nothing else can bind to &&), we may have decided to avoid passing it by value to c, seeing that it isn't going to be needed any more. If it now turns out that more code is to be added (or existing code reordered), we might indeed easily end up with something like: void foo(X&& x) { a(x); ... b(x); ... c(std::move(x)); ... d(x); //dang ... } However, I'd still say that this evil is far lesser than what you can get from pointers gone bad. The behavior of the program will be far more deterministic and the error should be far easier to discover and fix. Besides, does one indeed make modifications to a large and complicated function without taking some time first to see what it does? And if you really wanted to optimize, wouldn't it be better if there was one or two well-known and robust idioms, rather than a plethora of ad hoc hacks that might be otherwise invented? |
axilmar
Member #1,204
April 2001
|
The move capability of C++1x will increase performance of the language in speed tests, but it does not scale to many developers, multiple changes and projects that take years to complete. It's simply a mistake of Stroustrup and Co. that they will regret a few years from now, just like they did with std::auto_ptr. The Academia literally screams about how destructive updating is harmful to compilers and CPU performance and parallelization/concurrency, yet Stroustrup and Co. put more destructive updating in the language... |
anonymous
Member #8025
November 2006
|
May-be instead of appealing to some "Academy", you give a link to some article that discusses the issues? It might be more enlightening. Has auto_ptr wreaked havoc in practice (any stories?), rather than just being generally avoided? I haven't had any problems using it safely (e.g to hold a pointer in a non-copyable class, although I nowadays I tend to use boost::scoped_ptr instead - and unique_ptr would be good for noncopyable but moveable classes). |
Sevalecan
Member #4,686
June 2004
![]() |
Off hand, I can see no problems with auto_ptr. I mean, I'd really have to search the net to find out whatever it is you're complaining about. Assuming anyone there knows. I just see no obvious problems with a scoped pointer class, except maybe the fact that there isn't one for arrays or something. Is it possible that you and all the people you're arguing for just suck at programming to some amazing degree that no half-witted person can even comprehend? TeamTerradactyl: SevalecanDragon: I should shoot you for even CONSIDERING coding like that, but I was ROFLing too hard to stand up. I love it! |
Goalie Ca
Member #2,579
July 2002
![]() |
axilmar said: The Academia literally screams about how destructive updating is harmful to compilers and CPU performance and parallelization/concurrency, yet Stroustrup and Co. put more destructive updating in the language... Well being an academic and having published in this area bitching about the difficulties of state in multi-core I feel I have to clarify. This std::move is a good thing for its intended use. This is yet another case of an optimization that can't really be infered by a compiler. There are a lot of people in the academic community who have been trying for decades to figure out how to get compilers to be smart enough to figure out code and do really smart things with it. The problem is that you can't really prove anything in a language like C++. You really need "annotations" added by human programmers in order to tell the compiler it's okay to do some things. In this case there is more to it than that because the programmer also has to supply the alternate code path as well. But the point is, there are a number of places where this will be a good optimization. I really doubt that C++ will be the standard multi-core language. It has another niche to fill. ------------- |
axilmar
Member #1,204
April 2001
|
Sevalecan said: Off hand, I can see no problems with auto_ptr. I mean, I'd really have to search the net to find out whatever it is you're complaining about. Assuming anyone there knows. I just see no obvious problems with a scoped pointer class, except maybe the fact that there isn't one for arrays or something. Is it possible that you and all the people you're arguing for just suck at programming to some amazing degree that no half-witted person can even comprehend? Perhaps. On the other hand: http://groups.google.com/group/comp.std.c++/browse_frm/thread/e60adecf1427635b?hl=en&pli=1 Quote:
I consider auto_ptr very useful, but error prone due to its The above is found in the first google results page. |
|
|