I have a function which produces a type of expensive object (containing vectors and a maps of a non fixed size) so I really want to avoid invoking copy c'tors.
Until now I have just returned a std::shared_ptr from the method and used that but I think it is ugly and requires typedeffing to be really usuable.
I am aware of two thing that may help me. Firstly copy elision and the second is the move semantic.
My problem is that I know how to use neither properly. My research has told me that copy elision is entirely done by compiler and is not apart of the st'd. I don't really want to have to solely rely on this.
So how do I ensure that move assigment is invoked and does having it in place going to prevent the compiler from doing to copy elision.
ResultSet &&generateResults()
{
//ResultSet a(); :S
ResultSet a;
a.populat(...
//blah blah blah
return a;
}
//else where (where the && assignment operator is overloaded
ResultsSet b = generateResults();
In this case is this the most correct way to code this? and if not how could I improve it. I am happy to use C++0x only constructs.
BTW: My compiler is gcc 4.6
A good answer to your questions can be found in this blog post series by Dave Abrahams:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
It covers interactions among rvalue references, move constructors and copy elision. It's a bit long but it is worth to read the whole thing :)
The short story is that copy elision has the precedence. If for some reason it does not (or cannot) happen, the compiler must first consider the move constructor and finally the copy constructor.
In this case is this the most correct way to code this?
Actually, it is the "least correct" way: you are returning a reference to an automatic object. When the function returns, the client receives a reference to an object that no longer exists.
There is no difference between lvalue references and rvalue references in this respect. So just get rid of the rvalue reference and return the result by value. You will either get NRVO or move semantics.
If you don't like reading ,here is a link to a video about rvalues and move-semantics: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n
Your research is wrong. Copy elision is absolutely Standard. It is not mandated but officially allowed. In the example of your function, I would definitely expect it to be applied, as the transformation is relatively trivial.
And secondly, you should not return an rvalue reference- just return by value. The compiler isn't mandated to elide the copy- although it probably still will- but it must invoke move semantics.
Oh, and you need to overload the move constructor, not the move assignment operator, for that specific piece of code, although of course ideally you would do both.
ResultSet a();
Does not define any variable, but declares a function called a
taking nothing and returning a ResultSet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With