|
Boost : |
From: Daniel Frey (d.frey_at_[hidden])
Date: 2002-10-22 15:14:42
On Tue, 22 Oct 2002 21:33:41 +0200, Andrei Alexandrescu wrote:
> "Daniel Frey" <d.frey_at_[hidden]> wrote in message
> news:ap470c$u81$1_at_main.gmane.org...
>> URVO is preferable, yes. It works almost everywhere, but sometimes -
>> like for operator+ - the URVO can't help, you need the NRVO.
>
> Why can't it help?
>
> T operator+(const T& lhs, const T& rhs) {
> return T(lhs) += rhs;
> }
this is equivalent to:
T operator+( const T& lhs, const T& rhs ) {
return T( lhs ).operator+=( rhs );
}
You return the result provided by operator+=. operator+= might be
implemented in a different compile-unit. Even if it isn't and the compiler
could figure out that operator+= returns *this (the temporary created
above), it is not allowed to apply any optimization except
a) it can guarantee that there are no observable side effects
or
b) the standard explicitly allows optimizations that needn't care about
observable side effects (see §3.7.2/2 and §12.8/15).
While a) is hard to figure out for a compiler and I haven't seen any
compiler that implements it for non-trivial classes, b) is your only hope
to eliminate the temporary. And 'return T(lhs)+=rhs;' only looks like a
case for URVO, but it isn't. Try it out...
>> In these cases I
>> think it's essential to help the compiler:
>>
>> T f()
>> {
>> T nrv;
>> // add your code here ...
>> return nrv;
>> }
>
> But an explicit move constructor such as:
>
> T f()
> {
> T nrv;
> // add your code here ...
> return T(nrv, move);
> }
>
> /always/ transforms an lvalue into a temporary at a small cost. So the
> idiom above works efficiently on compilers that do URVO or NRVO, while
> your idiom works only on compilers that support NRVO (which I understand
> are a subset of the former).
If the compiler implements NRVO, it cannot be made any better - the
temporary is simply eliminated completely. If the compiler doesn't
implement the NRVO, Mojo may be the best pattern. As you can see from the
patch to operators.hpp, boost can provide both. Maybe you want to add a
Mojo-friendly implementation of the non-NRVO version? ;)
> So I'd say for programmers who want to make their code efficient on more
> platforms, the latter idiom is better. The disadvantage, of course, is
> that T needs to implement that constructor.
I still hadn't the time to look at Mojo II, but if you can use only ONE
implementation, Mojo might be best for now. For the future, I think more
and more compilers will implement the NRVO. (Personally I'd be very
interested to hear about the VC++7, but for some reason no-one here seems
to test it and tell us the result :o). The GCC at least has a working NRVO
and if a free compiler can do it, shouldn't you expect the people that
*sell* compilers can do it, too? ;)
(Obviously, Mojo has more advantages and can help to reduce the cost of a
lot more copies, but this is another issue...)
Regards, Daniel
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk