Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

passing heavy objects C++0x

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

like image 345
111111 Avatar asked Jun 18 '11 16:06

111111


4 Answers

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.

like image 68
bluescarni Avatar answered Nov 10 '22 05:11

bluescarni


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.

like image 29
fredoverflow Avatar answered Nov 10 '22 04:11

fredoverflow


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

like image 35
engf-010 Avatar answered Nov 10 '22 04:11

engf-010


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.

like image 3
Puppy Avatar answered Nov 10 '22 05:11

Puppy