C steals a few neat things from Lisp: "(almost!) anything is a value".

Everybody who knows C knows that assignments are rvalues. Given appropriate types, you can say:

a = b = c;
"operator=" (the C++ term) is right associative, so here's what it does:
  1. assigns the value of c to b.
  2. assigns the (new) value of b to a.

In C++, we can overload operator=; for a builtin type T it has the signature

T& operator=(T& a, S b);
By convention, operator= returns its LHS by reference.

So in C++ this is legal syntax!

(a = b) = c;
It's obviously not legal C: there, sanity prevails and the result of an assignment is an rvalue, not an lvalue. But C++ allows it; it means:
  1. Assign the value of b to a (using a.operator=(b) or operator=(a,b)).
    This always has a side effect (the value of a changes), but since operator= is user-defined, it can have additional side effects (for an example see autoptr or almost any smart pointer).
    In any case, (a=b) is an lvalue, so we can now...
  2. Assign the value of c to the lvalue (a=b), by convention to a.
So (assuming convention holds!) b, like c remains unchanged (indeed, b needn't be an lvalue; it's not a reference!), and a changes its value twice.

Another side effect of adding operator overloading to C, and trying to keep things orthogonal...


yaweh explains how to overcome this in your own classes. But for "int a,b,c;", the code in the title works! Perhaps it's because having "&(a=4)" return a const int* would be too much, even for C++-heads.

In order to prevent this oddity in syntax, all one must do is have the operator= method return a constant reference:

  class T
  {
    ...
  public:
    const T& operator=(const T&);
  };

The main use of references is to avoid the overhead of passing/returning by value, while maintaining the same syntax (no pointer dereferencing). References should always be declared const unless the object they reference is meant to be altered.

Log in or registerto write something here or to contact authors.