Nytt rim från denna påsk. PåskRimBondBers. Lite i sista laget kanske men det verkar ju vara så det är nu för tiden. Allt för lite tid för poesi, eller vad man nu skall kalla det ;-) Gott slut på påsken!
Copying big objects has always been a problem and somethings that you want to avoid. Things you have to think about is using reference to const in parameter so you don't get expensive copies. Smart pointer with reference counting is another way to avoid copying. Smart compilers can also avoid some copying that can be optimized away. One example of this is the return value optimization were the temporary object returned from a function is used directly, without copying, to initialize the object holding the value after the function call.
Still there are more temporaries to be avoided and the thing called move semantics or rvalue references are here to achieve that. It seems easy to explain but since much of this with temporaries are, if not hidden to the user, so not as obvious at least, and not what you normally think a lot about when solving coding problems. So we are probably up to one or more surprises here as we go along and I'm afraid that this is probably not a silver bullet for avoiding needless copies.
I'll come back with some code examples shortly.
Started to write under the label CPlusPlus11 for the new C++11 stuff. So much time has passed since the standard was released so I guess the old name C++0X is now almost forgotten. Better leave it that way.
Time to investigate the new move semantics, or at least what I have understood about it! So what is it? It is a way to specify how object state can be moved instead of copied.
Why is that interesting? Well if copying really isn't necessary, since the object just being copied is never going to be used again ever, then we could just move the state instead of making a copy. No more unnecessary copies. Now this is the normal life for temporaries, so called rvalues. They are created, used and sometimes their values are copied to a resulting variable, a lvalue. During this process a move could be deployed instead of a copy so that the lvalue got its state from a rvalue.
More good news is that the compiler knows when this situation occurs. So your code could benefit from this even without a single change. It is something like the return value optimization but there the compiler can even avoid the move altogether and place the result in the right spot from the beginning. As we will see there seems to be some things that complicates this picture a bit.
How does this work then? In order to specify how the move is to be performed we need to create one new type of constructor, the move ctor. This is like the copy-ctor except that it takes a rvalue reference identified by T&&. Note the notation with the double ampersands. A move ctor for class Class would thus be declared like this:
Class(Class&& c)
This ctor defines how the state is moved from the Class object c instance to this object instance. The body of the ctor will of course depend on the implementation of Class. If it has some members that can efficiently be moved then we are in business.
So with this ctor defined everytime a move can be performed this ctor is called. If we had not defined this ctor then the Copy-ctor would be used instead. So there is a fallback solution - how it worked with old versions of the compiler.
The assignment operator can also be defined in a similar way.
Class& operator=(Class&& c)
Getting the predefined macros from a compiler might be the first thing you should do to learn your tools but in my case it seem to be the last thing I do. To get to the info has in my case often required reading through long an boring manuals. However in the case of gcc there is simple way to get the info directly from the compiler itself.
It goes like this.
echo | gcc -E -dM -
The option -E tells gcc just to run the preprocessor. -dM tells the preprocssor to output all defines.
The final twist is to use stdin to enter the code which in this case is just whitespace. There are other ways do that but I like this pipe version.