As I\'ve understand, when overloading operator=, the return value should should be a non-const reference.
A& A::operator=( const A& )
{
// check for sel
I'm not sure how often you'd want to do it, but something like: (a=b)=c;
requires a reference to work.
Edit: Okay, there is a bit more to it than that. Much of the reasoning is semi-historical. There's more reason you don't want to return an rvalue than just avoiding an unnecessary copy into a temporary object. Using a (minor) variation on an example originally posted by Andrew Koenig, consider something like this:
struct Foo {
Foo const &assign(Foo const &other) {
return (*this = other);
}
};
Now, assume you're using an old version of C++ where assignment returned an rvalue. In that case, (*this=other);
will yield that temporary. You're then binding a reference to the temporary, destroying the temporary, and finally returning a dangling reference to the destroyed temporary.
Rules that have been enacted since (extending the life of a temporary used to initialize a reference) would at least mitigate (and might completely cure) this problem, but I doubt anybody re-visited this particular situation after those rules had been written. It was a bit like an ugly device driver that includes kludges to work around dozens of bugs in different versions and variations of the hardware -- it could probably be refactored and simplified, but nobody's quite sure when some seemingly innocuous change will break something that currently works, and ultimately nobody wants to even look at it if they can help it.
If it returned a copy, it would require you to implement the copy constructor for almost all non-trivial objects.
Also it would cause problems if you declare the copy constructor private but leave the assignment operator public... you would get a compile error if you tried to use the assignment operator outside of the class or its instances.
Not to mention the more serious problems already mentioned. You don't want it to be a copy of the object, you really do want it to refer to the same object. Changes to one should be visible to both, and that doesn't work if you return a copy.
Returning by reference reduces the time of performing chained operations. E. g. :
a = b = c = d;
Let's see the actions which would be called, if operator=
returns by value.
c
makes c
equal to d
and then creates temporary anonymous object (calls copy ctor). Let's call it tc
.b
is called. Right hand side object is tc. Move assignment operator is called. b
becomes equal to tc
. And then function copies b
to temporary anonymous, let's call it tb
.a.operator=
returns temporary copy of a
. After operator ;
all three temporary objects are destroyedAltogether: 3 copy ctors, 2 move operators, 1 copy operator
Let's see what will change if operator= will return value by reference:
c
becomes equal to d
, reference to lvalue object is returnedb
becomes equal to c
, reference to lvalue object is returneda
becomes equal to b
, reference to lvalue object is returnedAltogether: only three copy operators is called and no ctors at all!
Moreover I recommend you to return value by const reference, it won't allow you to write tricky and unobvious code. With cleaner code finding bugs will be much easier :) ( a = b ).f();
is better to split to two lines a=b; a.f();
.
P.S.:
Copy assignment operator : operator=(const Class& rhs)
.
Move assignment operator : operator=(Class&& rhs)
.
In real code (i.e. not things like (a=b)=c
), returning a value is unlikely to cause any compile errors, but it is inefficient to return a copy because creating a copy can often be expensive.
You can obviously come up with situation where a reference is needed, but those rarely -- if ever -- come up in practice.