Assignment Operator =
The assignment operator has a signature like this:
class MyClass
{
public:
...
MyClass& operator=(const MyClass &rhs);
...
}
MyClass a, b;
...
b = a; // Same as b.operator=(a);
Notice that the = operator takes a const-reference to the right hand side of the assignment. The reason for this should be obvious, since we don't want to change that value; we only want to change what's on the left hand side.
Also, you will notice that a reference is returned by the assignment operator. This is to allow operator chaining. You typically see it with primitive types, like this:
int a, b, c, d, e;
a = b = c = d = e = 42;
This is interpreted by the compiler as:
a = (b = (c = (d = (e = 42))));
In other words, assignment is right-associative. The last assignment operation is evaluated first, and is propagated leftward through the series of assignments. Specifically:
- e = 42 assigns 42 to e, then returns e as the result
- The value of e is then assigned to d, and then d is returned as the result
- The value of d is then assigned to c, and then c is returned as the result
- etc.
Now, in order to support operator chaining, the assignment operator must return some value. The value that should be returned is a reference to the left-hand side of the assignment.
Notice that the returned reference is not declared const. This can be a bit confusing, because it allows you to write crazy stuff like this:
MyClass a, b, c;
...
(a = b) = c; // What??
At first glance, you might want to prevent situations like this, by having operator= return a const reference. However, statements like this will work with primitive types. And, even worse, some tools actually rely on this behavior. Therefore, it is important to return a non-const reference from your operator=. The rule of thumb is, "If it's good enough for ints, it's good enough for user-defined data-types."
So, for the hypothetical MyClass assignment operator, you would do something like this:
// Take a const-reference to the right-hand side of the assignment.
// Return a non-const reference to the left-hand side.
MyClass& MyClass::operator=(const MyClass &rhs) {
... // Do the assignment operation!
return *this; // Return a reference to myself.
}
Remember, this is a pointer to the object that the member function is being called on. Since a = b is treated as a.operator=(b), you can see why it makes sense to return the object that the function is called on; object a is the left-hand side.
But, the member function needs to return a reference to the object, not a pointer to the object. So, it returns *this, which returns what this points at (i.e. the object), not the pointer itself. (In C++, instances are turned into references, and vice versa, pretty much automatically, so even though *this is an instance, C++ implicitly converts it into a reference to the instance.)