Boost logo

Boost :

Subject: Re: [boost] Is self assignment test valid?
From: David Abrahams (dave_at_[hidden])
Date: 2008-09-08 16:52:25


on Mon Sep 08 2008, "Niels Dekker - no return address" <noreply-AT-this.is.invalid> wrote:

> Andrei Alexandrescu wrote:
>> JoshuaMaurice (at) gm...com wrote:
>>> As an aside, the way I've generally done it is as follows, which
>>> I assume to be equivalent to the two previous examples.
>>>
>>> struct T
>>> {
>>> T& operator= (T const& x)
>>> {
>>> T(x).swap(*this);
>>> return *this;
>>> }
>>> void swap(T& x);
>>> };
>>
>> That's the politically correct version. It turns out that, when a
>> function needs to make a copy of its argument, it better takes it by
>> value in the first place. That way, if an rvalue is passed in, the
>> compiler can directly fuse the rvalue to the parameter thus saving a
>> copy.
>
> Do you think this is still relevant when operator= is inline, and it's just
> doing "T(x).swap(*this)"?

Absolutely. The compiler is allowed to elide the implicit copy when the
argument is an rvalue if the corresponding parameter is taken by-value.
However, when you write

     T(x)

and x is an lvalue (as it is inside the operator= above), the compiler
is required to honor your explicit instruction to make a copy of x.

> If so, I might consider submitting another ticket regarding
> boost::function, which still copy-assigns in the "politically correct"
> way at the moment. As so many of us do :-)

Could you do that for all the other libraries too? I'm serious, I've
been meaning to make a sweep across the source code to fix this.

>> See http://www.erdani.org/publications/cuj-02-2003.html
>
> Thanks! Looking a the example of passing the result of MakeUrl() to the
> function Connect(const String& url), you wrote: "For a compiler to optimize
> away the copy, it has to do the Herculean job of (1) getting access to
> Connect's definition (hard with separately compiled modules), (2) parse
> Connect's definition to develop an understanding of it, and (3) alter
> Connect's behavior so that the temporary is fused with finalUrl."
>
> Now is it still such a Herculean job for a compiler to do so for an /inline/
> assignment operator that's only just swapping a temporary copy? Honestly, I
> haven't done any profiling on this, so I just hope you did so already :-)

Yes, it's still a fairly herculean job. The compiler would have to
prove that the entire program works exactly the same way with or without
the copy, proving that nothing about the address or identity of the new
T is significant. While it's possible that someone might implement that
optimization for some cases where T's copy constructor, swap, and
destructor are all inlined, that level of understanding is not typically
developed in optimizers.

In the case of copy-elision for by-value arguments and return values,
the compiler is explicitly allowed to _assume_ there is no semantic
difference between the original rvalue and its copy. That's low-hanging
fruit for a compiler writer, that pays huge dividends.

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

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