views:

180

answers:

4

In C++, the concept of returning reference from the copy assignment operator is unclear to me. Why can't the copy assignment operator return a copy of the new object? In addition, if I have class A, and the following:

A a1(param);
A a2 = a1;
A a3;

a3 = a2; //<--- this is the problematic line

The operator= is defined as follows:

A A::operator =(const A& a)
{
    if (this == &a)
    {
        return *this;
    }
    param = a.param;
    return *this;
}
+11  A: 

Because the semantics of C - hence C++ require that the value of the assignment operator be an l-value itself to allow (among other things):

a = b = 0;

References have that property, r-values don't.

msw
The requirement is not that the *value* is an lvalue, but that the *expression* `a = b` is an lvalue. The distinction between lvalues and rvalues is one of *expressions*, not objects/values or whatever.
FredOverflow
Actually, while the left-hand side of the assignment operator must be an lvalue, in C result of the assignment expression *is not* an lvalue (unlike in C++). Chaining of the assignment operator doesn't require it to evaluate to an lvalue, since the assignment operator is 'right-to-left' associative (by the C grammar).
Michael Burr
+3  A: 

It's partly because returning a reference to self is faster than returning by value, but in addition, it's to allow the original semantics that exist in primitive types.

DeadMG
Not going to vote down, but I'd like to point out that returning by value would make no sense. Imagine (a = b = c) if (a = b) returned 'a' by value. Your latter point is very legit.
You'd get (a = (b = c)), I believe, which would still produce the intended result. Only if you did (a = b) = c would it be broken.
DeadMG
A: 

operator= can be defined to return whatever you want. You need to be more specific as to what the problem actually is; I suspect that you have the copy constructor use operator= internally and that causes a stack overflow, as the copy constructor calls operator= which must use the copy constructor to return A by value ad infinitum.

MSN
jpalecek
@jpalecek, I agree, but given the original post and lack of clarity when stating the actual problem, it is most likely that the assignment operator executing results in a stackoverflow due to infinite recursion. If there is another explanation for this question I would love to know it.
MSN
+8  A: 

Strictly speaking, the result of a copy assignment operator doesn't need to return a reference, though to mimic the default behavior the C++ compiler uses, it should return a non-const reference to the lvalue that is assigned to (an implicitly generated copy assignment operator will return a non-const reference - C++03: 12.8/10). I've seen a fair bit of code that returns void from copy assignment overloads, and I can't recall when that caused a serious problem. Returning void will prevent users from 'assignment chaining' (a = b = c;), and will prevent using the result of an assignment in a test expression, for example. While that kind of code is by no means unheard of, I also don't think it's particularly common - especially for non-primitive types (unless the interface for a class intends for these kinds of tests, such as for iostreams).

I'm not recommending that you do this, just pointing out that it's permitted and that it doesn't seem to cause a whole lot of problems.

These other SO questions are related (probably not quite dupes) that have information/opinions that might be of interest to you.

Michael Burr