C++ Default, Copy and Move Constructors
This is the next part after object lifetime.
Series navigation: Previous: Constructor overload and delegating constructors | Next: Copy assignment and move assignment
The goal is to understand which constructor runs when an object is created, copied, or moved.
Constructor types
| constructor | when it runs |
|---|---|
| Default constructor | Create an object without arguments. |
| Copy constructor | Create a new object from an existing object. |
| Move constructor | Create a new object by taking resources from a temporary object. |
Default constructor
A default constructor can be called without arguments.
Example:
If a class has no constructors, the compiler can create a default constructor. If you write another constructor, the compiler does not always create a default constructor for you.
You can ask the compiler to create one:
Copy constructor
A copy constructor creates a new object from an existing object.
The source object r1 is still valid after the copy.
Typical signature:
copy constructor use reference with const that we can't change the source object by mistake
Use const Robot& because:
constmeans the copy constructor should not change the source object.&avoids copying the object again while trying to copy it.
Move constructor
A move constructor creates a new object by taking data from a temporary object.
It can also run when using std::move:
Typical signature:
&& means rvalue reference. It can bind to temporary objects and to objects
converted with std::move.
After moving, the moved-from object must still be valid, but its value may be empty or changed.
Full example
Notes about output
Modern C++ compilers are allowed to skip some copies and moves using copy elision. This means the output can be shorter than expected.
For learning, you can disable copy elision with:
Series navigation: Previous: Constructor overload and delegating constructors | Next: Copy assignment and move assignment
Without -fno-elide-constructors, this line may not print a move constructor:
That is normal.
Rule of thumb
- Use the default constructor when an object can start with a normal empty/default state.
- Use the copy constructor when the new object should have the same value as another object.
- Use the move constructor when the new object can take resources from a temporary object.
- Prefer normal values and standard library types first. Write custom copy/move constructors only when the class owns a resource directly.
Note about move
Move does not destroy the source object.
After this line:
For example, if Robot owns a std::string name, the move constructor may move the string buffer from b.name into d.name.
So after the move:
b.name is still safe to access, but its value is unspecified. Commonly it becomes an empty string, but you should not rely on that.
Run online
Copy the full example above and run it in the embedded OneCompiler C++ runtime.
Run locally
Save the example as main.cpp:
For learning copy and move behavior:
Online compilers: OneCompiler | Compiler Explorer | Wandbox