C++ Why the Assignment Operator Should Return a Const Ref in Order to Avoid (A=B)=C

C++ why the assignment operator should return a const ref in order to avoid (a=b)=c

(x=y) means x.operator=(y), which returns the object x. Therefore, (x=y)=z means (x.operator=(y)).operator=(z). The expression in parens sets x to y and returns x, and then the outer bit sets x to z. It does not set y to z as you might expect, and as the expression x = y = z does.

This behavior is counter-intuitive (they should all be equal after the assignment, right?); returning a const reference makes it impossible and avoids the problem.

Why must the copy assignment operator return a reference/const reference?

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 object 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.

  • Has anyone found the need to declare the return parameter of a copy assignment operator const?
  • Overloading assignment operator in C++

Assignment Operator Overloading in C++ Syntax Explanation

The reference means that avoid copying the object. As a result, it will return a reference to the same object. Moreover, it will provide lvalue as a result. And if you think about it, that's what you want to happen when the assignment operator is used.

Every object in C++ has access to its own address through this pointer.

That means that the you return the object itself.

If your question is why we use *this instead of this, then this happens because you need to dereference the pointer first, since the return type is a reference (and not a pointer for example).

Why not return const-reference in operator= instead of a reference?

You can, but the users of MyClass may be surprised.

Usually, references can be taken to assignments (and less often, assignments can be assigned again). This is slightly confusing to word correctly, so here's what it looks like:

int a = 4;
int &r = a = 5;
(a = 6) = 7;

This also disallows calling member functions that modify the arguments of the function, for example:

#include <iostream>

struct C
{
int value;
const C &operator=(int v){value = v; return *this;}
};

void assign_value(C &ref)
{
ref %= 4;
}

int main(void)
{
C test;
assign_value(test = 5);
std::cout << c.value << '\n';
}

Return type of assignment operator

Your class does not meet the CopyAssignable concept (§17.6.3.1) so it is no longer guaranteed by the standard to work with the standard containers that require this (e.g. std::vector requires this for insert operations).

Besides that, this behavior is not idiomatic and will be perceived as surprising by programmers using your code. If you want to disallow chaining, consider adding a named function that does the assignment instead.

Just don't try to change the behavior of idiomatic operators in subtle ways like this. It will make your code harder to read and maintain.

why assignment operator returns ref not pointer?

There's nothing preventing you from returning a pointer if you'd like (though, I don't see why), but if you want to mimick the behaviour of the integral types in c++ you return a reference.

Why should the assignment operator return a reference to the object?

The usual form returns a reference to the target object to allow assignment chaining. Otherwise, it wouldn't be possible to do:

Foo a, b, c;
// ...
a = b = c;

Still, keep in mind that getting right the assigment operator is tougher than it might seem.

why does builtin assignment return a non-const reference instead of a const reference in C++?

By design, one fundamental difference between C and C++ is that C is an lvalue-discarding language and C++ is an lvalue-preserving language.

Before C++98, Bjarne had added references to the language in order to make operator overloading possible. And references, in order to be useful, require that the lvalueness of expressions be preserved rather than discarded.

This idea of preserving the lvalueness wasn't really formalized though until C++98. In the discussions preceding the C++98 standard the fact that references required that the lvalueness of an expression be preserved was noted and formalized and that's when C++ made one major and purposeful break from C and became an lvalue preserving language.

C++ strives to preserve the "lvalueness" of any expression result as long as it is possible. It applies to all built-in operators, and it applies to built-in assignment operator as well. Of course, it is not done to enable writing expressions like (a = b) = c, since their behavior would be undefined (at least under the original C++ standard). But because of this property of C++ you can write code like

int a, b = 42;
int *p = &(a = b);

How useful it is is a different question, but again, this is just one consequence of lvalue-preserving design of C++ expressions.

As for why it is not a const lvalue... Frankly, I don't see why it should be. As any other lvalue-preserving built-in operator in C++ it just preserves whatever type is given to it.



Related Topics



Leave a reply



Submit