Concepts / Copy Assignment and Self-Assignment

Copy Assignment and Self-Assignment

Copying of an object of a class is defined by two members: a copy constructor and a copy assignment.

  • Programming

Why Copying Needs a Definition

When you copy an object of a class, the language needs to know exactly how that copy should be produced. There is no single rule that answers this for every class. Instead, copying an object of a class is defined by two members working together: a copy constructor and a copy assignment. Together these two members form the definition of copying for that class. They are the place to look whenever you want to understand what a copy of one of your objects will actually contain.

This article uses a class called Vector as its running example. The source presents Vector as a class that holds a pointer to an array of doubles and releases that array in its destructor. Because the object is responsible for a resource that lives outside its own fields, the way it is copied matters. The rest of this article shows how to find the two members that govern copying, how to read their declarations, and how to trace a copy problem back to them.

Tracing a Vector Copy

Start with a concrete situation. You have a Vector named a, and you want a second Vector named b that starts out as a copy of a. Before reading any further, decide for yourself: which member of the Vector class should the language use to produce b?

What do you think happens?

When a new Vector is created from an existing Vector a, which member of the Vector class is used?

  • The copy constructor

  • The copy assignment operator

  • The destructor

  • The element access function

Reveal answer
Answer:

The copy constructor

The source describes the copy constructor as the member used to create a new Vector from an existing Vector a. The copy assignment operator is the member that is used for assignment, which means it replaces the values of an object that already exists. The destructor releases the array, and the element access functions do not decide how a copy is produced.

The answer depends on whether the new object is being created or an existing object is being overwritten. Creating b from a is creation, so the copy constructor is the relevant member. Assigning a's values to an object that already exists is a different operation, and it uses the copy assignment operator instead. Keeping these two situations separate is the first step in reading any copy problem.

Two Members That Define Copying

Definition

Copying of an object of a class is defined by two members: a copy constructor and a copy assignment. The copy constructor is the member labeled as a constructor and is used to create a new object as a copy of another. The copy assignment is the member named as an assignment operator and is used when an existing object takes on the values of another object.

The two members are separate declarations inside the class, and the source lists both as the pair that defines copying. Neither one is optional in the sense of being implied by the other. When you want to know what a copy of a Vector will contain, you look at the class and find these two declarations rather than guessing from the rest of the class.

Vector classthe class being copiedVector(const Vector&a)copy constructorCopying a Vectorbehavior is defined hereVector&operator=(constVector& a)copy assignmentdeclaresdeclarescreates a new objectoverwrites an existing object
Which two members of the Vector class together control what happens whenever an object of that class is copied?

Reading the Vector Declaration

The source presents the whole Vector class and asks you to read it first as a list of responsibilities: the private data, the constructors and destructor, the copy members, and the element access functions. The sketch below is illustrative. It keeps the members the source names and the copy declarations exactly as the source states them, and it omits the bodies and any members not needed for this discussion.

Notes on the code
  • elem and sz are the private data: a pointer to an array and the element count
  • The destructor releases the array with delete[]
  • The two copy declarations are the members that define copying
  • The element access function does not decide how a copy is produced

Notice what the class holds. The member elem is a pointer to an array of doubles, and sz records how many there are. The destructor releases that array. So the object is responsible for a resource that lives outside its own fields. This is the reason the copy members deserve attention: a copy of a Vector has to deal with that resource, and the class must say how it does so.

Vector&return type: reference toVectoroperator=the assignment operatornameconst Vector&parameter: constantreference to the sourceathe object being copiedfrom
Where do the copy assignment signature's return type, name, and parameter each appear, and what does each part mean?

What a Plain Copy Does to the Array

The source does not show the bodies of the copy members, so it does not tell you what the Vector copy members must do in detail. What it does establish is that a copy has to deal with the array the object owns. Think about what the object holds: a pointer value in elem and a count in sz. If a copy only transferred the pointer value, the two objects would end up referring to the same array, and an action on one would be visible through the other. That is the situation the diagram below illustrates, and it is why the class must state its copying behavior explicitly rather than leave it to chance.

Vector asz valueselempointer to arraydouble arraythe resource both objectsuseVector bsz valueselemsame pointer valueholdspoints toholdspoints to the same array
After a copy that only transfers the elem pointer, what do the two Vector objects refer to, and why does a change through one affect the other?

Self-Assignment and the Assignment Operator

Self-assignment is the case where an object is assigned to itself. In the Vector class, that means the copy assignment's parameter a refers to the same object that the operator is running on. The provided source defines the copy assignment and its signature, but it does not show the body that handles this case, so this article does not claim how a particular implementation handles it. What you can reason about from the declaration is why the case needs attention: the operator both reads from its parameter and changes the object it belongs to.

Tracing a Copy Problem Back to Its Declaration

Worked example

Finding the governing member for an unexpected copy

A program that uses Vector objects behaves unexpectedly after one Vector is copied into another. Where do you look first, and how do you decide which member is responsible?

  1. 1
    Identify the kind of copy

    Decide whether a new object is being created from an existing one or an existing object is being overwritten. Creation points to the copy constructor. Overwriting points to the copy assignment.

  2. 2
    Open the class declaration

    Find the Vector class declaration. The source says copy behavior is defined by the copy constructor and copy assignment, so these two declarations are where the investigation starts.

  3. 3
    Read the matching declaration

    Read Vector(const Vector& a); for creation or Vector& operator=(const Vector& a); for assignment. Confirm which parameter is the source and that it is declared const.

  4. 4
    Ignore unrelated members at first

    The element access functions and other members do not decide how the copy is produced, so they are not the first place to look for a copy problem.

Result

The governing member is the copy constructor or the copy assignment, chosen by whether the copy creates a new object or overwrites an existing one. Reading that declaration narrows the search to the code that produces the copy.

Mistakes Learners Make with Copy Members

  • Common mistake

    Treating the copy constructor and the copy assignment as the same member

    What it looks like

    Assuming that Vector b(a); and b = a; both run the same function.

    Why it fails

    The source lists two separate declarations. The copy constructor creates a new object, while the copy assignment operator is named operator= and is used for assignment to an existing object.

    Do this instead

    Check whether the copy creates a new object or overwrites one, then read the matching declaration.

  • Common mistake

    Looking only at the element access functions when a copy goes wrong

    Why it fails

    The source states that the element access functions do not decide how the copy is produced.

    Do this instead

    Start with the copy constructor and copy assignment declarations in the class.

  • Common mistake

    Assuming a class that owns a resource needs no explicit copy members

    Why it fails

    The Vector class holds a pointer to an array and releases it in its destructor, so the copy has to deal with a resource outside the object's fields. The class must state how that is done.

    Do this instead

    When a class manages a resource, read its copy members to see exactly what a copy contains.

  • Common mistake

    Reading the copy assignment's parameter as something that will be modified, when it is declared const

Practice Locating Copy Behavior

MEDIUM

A class Matrix holds a pointer to a block of doubles and releases it in its destructor. Its declaration includes a copy constructor written as Matrix(const Matrix& m); and a copy assignment written as Matrix& operator=(const Matrix& m);. A colleague says that the element access functions decide what a copy of a Matrix contains. Explain, using the Vector example, why that claim is wrong, and name the two declarations you would read first.

Hints
  • Ask which two members the source says define copying for a class.
  • Think about whether the copy constructor and copy assignment are separate declarations.
  • Consider what the class holds outside its own fields and why that matters for copying.

Key Takeaways

  • Copying an object of a class is defined by two members together: a copy constructor and a copy assignment.
  • The copy constructor creates a new object from an existing one, while the copy assignment operator, named operator=, is used for assignment.
  • A class that holds a resource outside its own fields, such as a Vector with a pointer to an array of doubles, must state its copying behavior explicitly.
  • When tracing a copy problem, start by locating the copy constructor and copy assignment in the class declaration rather than the element access functions.
  • Self-assignment is a case to check in the copy assignment, because the parameter and the object can be the same object.

Related concepts

More concepts starting with C