If you're worried that returning the wrong thing might silently cause unintended side effects, you could write your operator=()
to return void
. I've seen a fair bit of code that does this (I assume out of laziness or just not knowing what the return type should be rather than for 'safety'), and it causes few problems. The kind of expressions that need to use the reference normally returned by operator=()
are pretty rarely used, and almost always easy code an alternative for.
I'm not sure I'd endorse returning void
(in a code review I'd probably call it out as something you shouldn't do), but I'm throwing it out there as an option to consider if you want to not have to worry about how oddball uses of the assignment operator might be handled.
late edit:
Also, I should have originally mentioned that you can split the difference by having your operator=()
return a const&
- that will still permit assignment chaining:
a = b = c;
But will disallow some of the more unusual uses:
(a = b) = c;
Note that this makes the assignment operator have semantics similar to what it has in C, where the value returned by the =
operator is not an lvalue. In C++, the standard changed it so the =
operator returns the type of the left operand, so it is an lvalue, but as Steve Jessop noted in a comment to another answer, while that makes it so the compiler will accept
(a = b) = c;
even for built-ins, the result is undefined behavior for built-ins since a
is modified twice with no intervening sequence point. That problem is avoided for non-builtins with an operator=()
because the operator=()
function call is a sequence point.
void
. That will stop(a=b)=c
,a=(b=c)
and any other such shenanigans that might have revealed the difference between a value and a reference. – Steve Jessop