CS 70

Use Phase (and the Assignment Operator)

Once we've created a value (and before we destroy it), we generally use it in some way. One common action is assigning an entirely new value with =.

Use Phase for Primitive Types

  • LHS Cow speaking

    When working with primitive types like int or float, we can access and change the value of a variable during its use.

For example, we can access an already initialized variable named x, by passing it into a function or assigning it to another variable:

int y = x;     // Here y is being initialized, but x is being used!
printMoos(x);  // Another use of x

We can also change its value through assignment:

x = 5;         // the value 5 is copied into the memory representing x

Use Phase for Instances of Classes

The way an instance of a class can be used is defined by its interface. During use, we can do the following with an instance of a class:

  • Access any public data members it might provide; all of its data members are also in use.
  • Call its public member functions.
  • Make copies of it using the copy constructor.
  • Pass it as an argument to a function (which, for nonreference parameters, involves using it to copy-construct the parameter variable).
  • LHS Cow speaking

    One particularly interesting member function is the assignment operator.

The assignment operator changes one existing instance of a class to look exactly like another existing instance of the class.

Suppose we have

Leopard sabor{40};      // Sets sabor's spots_ = 40
Leopard siri{42};       // Sets siri's spots_ = 42

Then, if we write

sabor = siri;           // Assign siri to sabor

we are implicitly calling the Leopard class's assignment-operator member function, which is the same as writing

sabor.operator=(siri);  // Call sabor's operator= function with siri as an arg.

This function will be responsible for making sure that sabor's data members are changed to be the same as siri's.

Synthesized Assignment Operator

  • Cat speaking

    So… assignment operators seem pretty important! Will the compiler synthesize those for us, too?

  • LHS Cow speaking

    Yes!

The synthesized assignment operator will go through each data member in the class and set the data member in the left-hand object equal to the same data member in the right-hand object using that type's assignment operator!

  • RHS Cow speaking

    In our Leopard class, it would do exactly the right thing, by making the spots_ data member 42 in both Leopard objects.

  • LHS Cow speaking

    But in the next lesson, we'll see that sometimes it's important to write our own assignment operator.

Assignment Operator Specification

Code Assignment Operator? Who's Writing It?
operator = (const Cow& other); Yes You
operator = (const Cow& other) = default; Yes The compiler
operator = (const Cow& other) = delete; No No one

Notes

  • For the default form, the synthesized assignment operator assigns all the data members in the Cow object it was called on (the left side of the =) to have the values of the ones in Cow other (the right side of the =).
    • Each data member will follow the rules we've seen so far: primitives will be assigned as usual, and class instances will have their own assignment operators called.
    • If the member is an array, it loops through the array and assigns each element individually, starting at the first element and going to the last.
  • For the delete form, there is no assignment operator, and the compiler should not synthesize one. Thus trying to assign a Cow to another Cow (e.g., bessie = mabel;) will cause a compiler error.

Assignment vs. Copy Construction

  • RHS Cow speaking

    In this snippet, are we using the assignment operator or the copy constructor?

Cow mabel{7, 3};
Cow bessie = mabel;
  • Dog speaking

    Oh! It's… uh… its…. Hmph. I don't know!

What do you think?

Both assignment and copy-initialization can involve an equals sign (=) in code, and, because they both involve duplicating existing values, it's easy to mix them up!

When in doubt, remember

  • We use the copy constructor to initialize a brand-new object, making it a copy of an existing object.
  • We use the assignment operator to change an existing object, making it the same as another existing object.

Practice Exercise

Consider the following C++ program:

1| int main() {
2|     Cow bessie;
3|     Cow mabel = bessie;
4|     Cow daisy;
5|     daisy = mabel;
6|     return 0;
7| }

How many times will the Cow assignment operator be called?

(When logged in, completion status appears here.)