Professional C__ - Marc Gregoire [85]
There are tools that are able to detect unfreed objects. These tools are discussed in Chapter 21.
Assigning to Objects
Just as you can assign the value of one int to another in C++, you can assign the value of one object to another. For example, the following code assigns the value of myCell to anotherCell:
SpreadsheetCell myCell(5), anotherCell;
anotherCell = myCell;
You might be tempted to say that myCell is “copied” to anotherCell. However, in the world of C++, “copying” only occurs when an object is being initialized. If an object already has a value that is being overwritten, the more accurate term is “assigned” to. Note that the facility that C++ provides for copying is the copy constructor. Since it is a constructor, it can only be used for object creation, not for later assignments to the object.
Therefore, C++ provides another method in every class to perform assignment. This method is called the assignment operator. Its name is operator= because it is actually an overloading of the = operator for that class. In the preceding example, the assignment operator for anotherCell is called, with myCell as the argument.
In the C++11 standard, the assignment operator as explained in this section is sometimes called the copy assignment operator because both the left-hand side and the right-hand side object stay alive after the assignment. This distinction is made because C++11 adds a new move assignment operator in which the right-hand side object will be destroyed after the assignment for performance reasons. This move assignment operator is explained in Chapter 9.
As usual, if you don’t write your own assignment operator, C++ writes one for you to allow objects to be assigned to one another. The default C++ assignment behavior is almost identical to its default copying behavior: It recursively assigns each data member from the source to the destination object. The syntax is slightly tricky, though.
Declaring an Assignment Operator
Here is another attempt at the SpreadsheetCell class definition, this time including an assignment operator:
class SpreadsheetCell
{
public:
// Remainder of the class definition omitted for brevity
SpreadsheetCell& operator=(const SpreadsheetCell& rhs);
// Remainder of the class definition omitted for brevity
};
Code snippet from SpreadsheetCellAssign\SpreadsheetCell.h
The assignment operator, like the copy constructor, takes a const reference to the source object. In this case, we call the source object rhs, which stands for “right-hand side” of the equals sign. The object on which the assignment operator is called is the left-hand side of the equals sign.
Unlike a copy constructor, the assignment operator returns a reference to a SpreadsheetCell object. The reason is that assignments can be chained, as in the following example:
myCell = anotherCell = aThirdCell;
When that line is executed, the first thing that happens is that the assignment operator for anotherCell is called with aThirdCell as its “right-hand side” parameter. Next, the assignment operator for myCell is called. However, its parameter is not anotherCell. Its right-hand side is the result of the assignment of aThirdCell to anotherCell. If that assignment fails to return a result, there is nothing to pass to myCell.
You might be wondering why the assignment operator for myCell can’t just take anotherCell. The reason is that using the equals sign is actually just shorthand for what is really a method call. When you look at the line in its full functional syntax, you can see the problem:
myCell.operator=(anotherCell.operator=(aThirdCell));
Now, you can see that the operator= call from anotherCell must return a value, which is passed to the operator= call for myCell. The correct value to return is anotherCell itself, so it can serve as the source