CS 70

Synthesized Constructors

Because they are so important, sometimes the compiler will automatically write (synthesize) a default and/or copy constructor for us. For many simple classes, the synthesized constructors are exactly what we want!

  • The synthesized default constructor is a constructor with an empty member-initialization list and an empty function body. As such, it initializes the member variables exactly as they are written in the class definition. If no initialization is specified in the class definition, the variables will be default initialized (which, for primitive types, means they will have indeterminate values).
  • The synthesized copy constructor copy initializes all member variables using the members of the object to be copied.

There are complicated rules that determine when the compiler will decide to synthesize one or more of these constructors (as well as some other functions that we'll discuss later on).

  • Hedgehog speaking

    Complicated rules? Oh, no. Are we about to learn a bunch of complicated compiler rules??

  • LHS Cow speaking

    Don't worry! In CS 70, we don't expect you to know the rules for when a particular constructor will be synthesized.

  • RHS Cow speaking

    Instead, we ask that you explicitly state in your class definitions (i.e., in the header files) whether a particular constructor is being written by you, should be synthesized by the compiler, or shouldn't be allowed.

We tell the compiler what to do with these constructors in the class's header file!

Let's look our options for specifying these constructors for the concrete example of a Cow class…

Default Constructor Specification

Code Default Constructor? Who Writes It?
Cow(); Yes You
Cow() = default; Yes The compiler
Cow() = delete; No No one

Notes

  • The second form (with default) gives us the synthesized default constructor we discussed above. Note that default here means the compiler should “do the usual thing”, not “make default constructor”.
  • The third form (with delete) results in no default constructor for the class, so trying to create an instance of the class with code like Cow bessie; will result in a compiler error.
  • Horse speaking

    Hay! Why does it say = default;? Is that to say it's the default constructor?

  • LHS Cow speaking

    No. It's to say “please write it”.

  • Hedgehog speaking

    What?? Why isn't it = synthesized; then?

  • Bjarne speaking

    Because default was already a keyword used for other things, and I didn't want to add an extra keyword to the language.

  • Goat speaking

    Meh. I'm all for avoiding work, but even I think that's pretty weak!

  • Duck speaking

    So we do the copy constructor the same way (and with the same keywords)?

  • LHS Cow speaking

    Yup!

Copy Constructor Specification

Code Copy Constructor? Who Writes It?
Cow(const Cow& other); Yes You
Cow(const Cow& other) = default; Yes The compiler
Cow(const Cow& other) = delete; No No one

Notes

  • The second form's copy constructor will copy all of the data members in the Cow class from the already existing Cow other to the new Cow being created.
    • Each data member will follow the rules we've seen so far: primitives will be copy initialized with the value from the other class, and instances of classes will have their own copy constructors called.
  • The third form means there is no copy constructor, so code like Cow bessie{mabel}; or Cow bessie = mabel; will cause compiler errors.
  • Dog speaking

    This is awesome! Can I get the compiler to write my parameterized constructors, too?!?

  • LHS Cow speaking

    Nope. How is it supposed to know what parameters to use or what to do with the values that are passed in?

  • Dog speaking

    Aw, shucks.

Exercise

We want to create a Chicken class, with

  • A default constructor that sets the member variables to values we choose
  • A copy constructor that just copy initializes all of the member variables

How should we declare these two constructors in the class definition?

We should declare them as

Chicken();                                // we will define our own constructor
Chicken(const Chicken& other) = default;  // we want a synthesized constructor
  • Horse speaking

    Why do we need to write = default;? Why can't we just leave it out?

  • LHS Cow speaking

    Remember that saying = default means that you want the compiler to synthesize the constructor. If you leave it out, you're saying that you're going to write that constructor yourself.

  • RHS Cow speaking

    Okay, we've seen a bunch of things. Let's head up to the parent page to check our progress so far and maybe take a break.

(When logged in, completion status appears here.)