Boost logo

Boost :

Subject: Re: [boost] rvalue ref best practices?
From: Daniel Larimer (dlarimer_at_[hidden])
Date: 2012-06-11 08:29:30


On Jun 10, 2012, at 4:38 PM, Ion Gaztañaga wrote:

> El 09/06/2012 22:49, Giovanni Piero Deretta escribió:
>> On Sat, Jun 9, 2012 at 9:21 PM, Daniel Larimer<dlarimer_at_[hidden]>
>> wrote:
>>> I am trying to define my library API and have been using rvalue
>>> references and have observed some patterns that I would like to run
>>> by the community.
>>>
>>> In c++03 I would pass almost everything by const& unless it was to
>>> be modified. This results in extra copies any time a temporary is
>>> passed.
>
>> As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
>> , if the function is likely to consume or copy the parameter, the
>> best solution is to pass by value. This means you'll only need to
>> provide a single overload.
>
> What do you mean by "consume"? Passing by value is good if you are going to construct a new object in your implementation. If you want to reuse resources of the passed object (memory from std::string, already constructed objects from a container...) passing by reference is the best choice. If you want to reuse resources from "*this", passing a const reference is the best way: implementing vector::operator=() with pass by value would be a terrible idea IMHO. You can catch temporaries by rvalue references to reuse external resources. For generic code, catching by value could do some premature pessimization.

I mean that a common design pattern is....

create some object.
set some parameters.
pass it to some function.

... never use it again...

The user code could look like:

some_method( move(x) )

Or it could look like:

some_method(x);

// this version does not allow some_mehtod(x) to be called forcing 'move()' to be used.
some_class::some_method( X&& x ) {
        this->member = move(x);
}

// this version means some_method(x) results in a hidden 'copy' unless the caller is 'smart enough' to do some_method(move(x)) to init the 'copy'.
some-class::some_method( X x )
{
        this->member = move(x);
}

In the first case:
some_method(move(x)) results in one move operation and it is explicit to the user that the object is 'going away'.
In the second case, the object is first moved into the temporary and then moved into the member, but the caller is not aware of the move, because they know it is copied unless the explicitly say to move it.

Moves are not free. A struct that has 10 members + a vector still has to 'copy' the other 10 members even if it can move the vector. This is where pass-by-value breaks down, I think.

Dan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk