Copy Constructors and Copy Operations
Of these four, the move operations are the ones that let a resource change hands.
When Duplicating an Object Is the Wrong Answer
Most people think of objects as things you can duplicate whenever you need a second one, and for many objects that instinct is fine. Some objects break that instinct. An object may be responsible for something valuable, such as a large collection of numbers or a running background activity. For these objects, duplication fails in one of two ways. Either duplicating the object is so expensive that it defeats the purpose, or duplicating it is simply not possible.
This article follows one question. When you need an object's contents to live in a different scope, how can the language give you that without duplicating the resource underneath? The technique that answers it is to relocate the object's resource to a new home instead of making a copy of it. That technique is called a move.
Tracing Who Owns the Resource
Before any detail about move operations, it helps to track a single question at each step: which object is responsible for the resource right now? Think of ownership as a single label that names the object currently responsible for the resource. Before a transfer, the label names the source object. The resource itself sits with that source.
Read the diagram carefully. The resource on the right is the same resource that was on the left. What changed is the label. The label moved from the source to the destination. The point of the change is that responsibility moves while the resource is not rebuilt. That is the core difference between a move and a copy, and the rest of this article builds on it.
Move Constructors and Ownership Transfer
Move semantics transfers a resource to a new scope instead of duplicating it. A move constructor lets an object move simply and cheaply, and it is the mechanism for transferring ownership.
The source names four kinds of member that together control a resource's lifetime: constructors, copy operations, move operations, and a destructor. Of these four, the move operations are the ones that let a resource change hands. Copy operations produce a second resource. Move operations take a resource that already exists and give it to another object. That is why moving is the tool to reach for when producing a second resource is unwanted.
The definition has two parts worth separating. The first part describes the result: an object moves from one scope to another, and the move is simple and cheap. The second part describes the purpose: the transfer is about ownership, so responsibility for the resource passes from one object to another. The word cheap is the key contrast with copying. A move does not need to build a fresh resource to match the old one.
A move constructor is the piece of a class that performs this handover when a new object is being created from an existing one. It changes the ownership label so that it names the destination. The source does not describe in detail what the source object is left holding after the handover. What it does establish is that responsibility for the resource has passed to the new object.
Copying Versus Moving Compared
Copying and moving both get an object's contents into another scope, but they do it in different ways. A copy creates a separate resource for the new object. A move gives the existing resource to the new object. The source describes the move as simple and cheap, while copying is either impossible or undesirable for the objects it considers. That contrast is the reason move semantics exists.
| Question | Copying | Moving |
|---|---|---|
| What happens to the resource? | A separate resource is created for the new object | The existing resource is handed to the new object |
| How many resources exist afterward? | Two independent resources | One resource, with one owner at a time |
| Cost | Work to build a fresh resource that matches the old one | Simple and cheap, as the source describes it |
| Possible for every object? | Not always. Some objects cannot be copied | Used when copying is impossible or unwanted |
| Which operation produces it? | Copy operations | Move operations |
Copying and moving compared on cost, outcome, and possibility
Thread and Large Vector as Candidates
The source gives two concrete cases that motivate the technique. In both, the goal is the same: get the object into the new scope without going through a copy.
Deciding Between a Copy and a Move
A program needs an object that represents a concurrent activity to be available in a different scope. Should the program copy the object or move it?
- 1Identify the object
The object is a standard-library thread, which represents a concurrent activity.
- 2Check whether copying is possible
A thread cannot be copied, so there is no duplicate to hand over.
- 3Choose the operation
Since no duplicate can be made, the object must be moved. The existing thread is given to the new scope.
- 4Repeat for the second case
A Vector holding a million doubles can be copied in principle, but the programmer does not want to copy it. The cost of duplicating those numbers is the reason to move it instead.
A thread is moved because it cannot be copied. A large Vector is moved because copying it is possible but undesirable. In both cases the object reaches the new scope without a copy.
The pattern in these two cases gives a practical test. Ask whether duplicating the object is impossible, or whether it is so expensive that it defeats the purpose. If either answer is yes, the object is a strong candidate for moving. The source's examples are objects that cannot be copied, such as a thread, and objects that should not be copied, such as a large Vector. Simple values are a different case, since the source does not present them as candidates for this technique.
Common Misreadings of Moves
Common mistake Thinking a move makes a second copy and then discards the first
Why it failsThe source says a move gives the existing resource to the new object. The resource is not rebuilt, so the move does not produce a second resource.
Do this insteadRead a move as a change of ownership. The same resource changes its owner.
Common mistake Treating moving as the default for every object
Why it failsThe source presents moving as the tool to reach for when producing a second resource is unwanted. Objects that can be duplicated cheaply do not need it.
Do this insteadMove when copying is impossible or wasteful. Copy when a second independent resource is actually needed.
Common mistake Assuming the source object's state after a move is fully described by the move itself
Why it failsThe source pack does not spell out what the source object is left holding after the handover. It only establishes that responsibility has passed to the destination.
Do this insteadDo not rely on the source object still owning the resource. Look up the specific class's documented behavior for the moved-from object.
Common mistake Assuming a move and a copy always cost the same, because both end with the object in a new scope
Predicting the Right Operation
Suppose you have an object that owns a very large collection of numbers, and you need that object's contents in a different scope while the original is no longer needed. Would you copy it or move it, and what does ownership look like once you have made your choice? Explain your answer in terms of cost and whether a second resource is wanted.
Hints
- Ask whether a second independent resource is actually needed.
- The source names a large Vector as a case where copying is possible but not wanted.
- A move changes the owner label. It does not rebuild the resource.
Summary of Move Reasoning
Copying and moving are two ways of getting an object into a new scope. Copying builds a separate resource, while moving hands the existing resource to a new owner. Move constructors transfer ownership by changing which object is responsible for the resource, and they do this simply and cheaply. Threads and large collections are the main candidates, because one cannot be copied and the other should not be copied.
At a glance
- A move transfers a resource to a new scope instead of duplicating it, which makes it simple and cheap.
- Ownership is a label naming the object responsible for the resource, and a move constructor changes that label to the destination.
- Copying creates a separate resource, while moving leaves one resource with one owner at a time.
- Objects that cannot be copied, such as a thread, and objects that should not be copied, such as a large Vector, are the main candidates for moving.