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
How to Receive a Lambda as Parameter by Reference
How to Typedef a Template Class
How to Encode a String to Base64 Using Only Boost
How to Get a Certain Element in a List, Given the Position
C++ Most Efficient Way to Convert String to Int (Faster Than Atoi)
How to Use Sendinput Function C++
C++ Concatenating _File_ and _Line_ MACros
Getting a Directory Name from a Filename
Linear Index Upper Triangular Matrix
How to Assign Multiple Values into a Struct at Once
Check the File-Size Without Opening File in C++
Concatenating Strings Doesn't Work as Expected
Disabling G++'s Return-Value Optimisation
Visual Studio: Link:Fatal Error Lnk1181: Cannot Open Input File