Object Oriented Programming in C++ is greatly strengthened by the new standards of modern C++. One of the features of modern C++ is the move constructor that allows you to move the resources from one object to another object without copying them. In this post, we list the move constructor types that we are using in modern C++.
Table of Contents
What is a constructor in C++?
The Constructor in C++ is a function, a method in the class, but it is a ‘special method’ that is automatically called when an object of a class is created. We don’t need to call this function. Whenever a new object of a class is created, the Constructor allows the class to initialize member variables or allocate storage. This is why the name Constructor is given to this special method. Here is a simple constructor class example below,
1 2 3 4 5 6 7 8 9 10 |
class myclass { public: myclass() { std::cout << "myclass is constructed!\n"; }; }; |
What is a move constructor in C++?
There are different constructor types in C++ Classes and the Move Constructor is one of these. Move Constructors not only used in classes but also used with struct and union data types. The Move Constructor is a constructor that allows you to move the resources from one object to another object without copying them. In other words, the move constructor allows you to move the resources from an rvalue
object into to an lvalue
object.
The Move Constructor of class T
is a non-template constructor whose first parameter is class_name&&
, const class_name&&,
volatile class_name&&
, or const volatile class_name&&
. It can be used with no other parameters or with the rest of the parameters all have default values.
This general syntax is also a syntax for the “Typical declaration of a move constructor” as in below,
1 2 3 |
class_name (class_name &&) |
Syntax to use Move Constructor,
1 2 3 4 5 |
class_name ( class_name && ) // Declaration { // Definition } // Definition |
For more details about this please see this below,
Object Oriented Programming in C++ is highly evolved by the new standards of modern C++. One of the features of modern C++ is the move constructor that allows you to move the resources from one object to another object without copying them. In this post, we list the move constructor types in modern C++
What are the move constructors used in C++?
Now let’s see move constructors used in C++,
Typical declaration of a move constructor
The typical declaration of a move constructor is a move constructor declaration method that has user defined declaration and definition parts, and this is how you can declare typical move constructor in a class.
An example with a class;
1 2 3 4 5 6 7 8 9 10 11 |
class Tx { public: Tx() = default; // Default Constructor Tx(Tx&& other) // A Typical Declaration of a Move Constructor { } } |
We can use move constructor with std::move
as in example below.
1 2 3 4 |
class Tx o1; class Tx o2 = std::move(o1); // Using Move Constructor with std::move |
For more details about this please see this below,
Default (forced) move constructor in modern C++
The default (forced) move constructor is a move constructor deceleration method that has forced by = default
option. This default
option is forcing a move constructor to be generated by the compiler, here is how you can do forcing move constructor in a class.
1 2 3 4 5 6 7 8 9 10 11 12 |
class Tx { public: std::string str; Tx() = default; // Default Constructor Tx(Tx&& other) = default; // Default (Forced) Move Constructor }; |
For more details about this feature please see this post below,
Trivial move constructor
The Trivial Move Constructor is a Move Constructor which is implicitly defined or defaulted and has no virtual member functions, no base classes. The trivial move constructor generally a constructor that comes from template class or base class. The move constructor selected for every direct base of T or for every non-static class type (including array of class type) of T
is trivial move constructor.
In general, the trivial move constructor is a constructor that makes a copy of the object representation by using std::memmove
, it operates like the trivial copy constructor. Note that, all POD data types (data types compatible with the C language) are trivially movable.
In modern C++ example, this simple Tx
class has a move constructor.
1 2 3 4 5 6 7 8 |
class Tx { public: std::string str = "LearnCPlusPlus.org"; }; |
Now, we can define a new Ty
class and we can use Tx
class as a base class as below.
1 2 3 4 5 6 7 8 9 |
class Ty : public class Tx // uses Tx as a base class { public: void print_str(){ std::cout << str << std::endl; } // This class has Trivial Move Constructor from Tx class }; |
As you see, this new Ty
class above has a trivial move constructor from Tx
class. Because it is implicitly defined or defaulted.
For more details about this feature please see this post below,
Eligible move constructor
Since C++11, the Eligible Move Constructor is a Move Constructor which is eligible if it is not deleted. This definition is changed after C++20, the Eligible Move Constructor is a Move Constructor which is eligible if it is not deleted, if it has any associated constraints that are satisfied, if it has no move constructor with the same first parameter type is more constrained.
Until C++20, the move constructor is eligible:
- if it is not deleted
Since C++20, the move constructor is eligible:
- if it is not deleted,
- and if it has any associated constraints that are satisfied
- and it has no move constructor with the same first parameter type that is more constrained.
A simple class has an eligible move constructor because it has a default move constructor that compiler automatically defines, in Modern C++ it is similar as below.
1 2 3 4 5 6 7 8 9 10 11 |
class Tx { public: std::string str = "LearnCPlusPlus.org"; Tx() = default; // Constructor Tx(Tx&& other) = default; // Move Constructor }; |
Now, we can define a new Ty
class and we can use one of Tx
classes above as a base class here.
1 2 3 4 5 6 7 8 9 |
class Ty : public class Tx // uses Tx as a base class { public: void print_str(){ std::cout << str << std::endl; } // This class has Eligible Constructor from Tx class }; |
Deleted move constructor
Assume that there is a T
x class example with a declared and defined move constructor that uses std::move
. We can delete this move constructor as below.
1 2 3 4 5 6 7 8 9 10 11 |
class Tx { public: std::string str; Tx() = default; // Constructor Tx(Tx&& other) = delete; // Deleted Move Constructor }; |
Implicitly deleted move constructor
Now, we can define a new Ty
class and we can use Tx
class as a base class as below.
1 2 3 4 5 6 7 8 9 |
class Ty : public class Tx // uses Tx as a base class { public: void print_str(){ std::cout << str << std::endl; } // This class has Implicitly-deleted Move Constructor from Tx class }; |
Deleted Implicitly-declared Move Constructor
As you can see deleted move constructors above, this Ty
class above has the implicitly-deleted move constructor from Tx
class. We cannot use a move constructor with std::move
as in example below:
1 2 3 4 5 |
class Ty o1; // class Ty o2 = std::move(o1); // ERROR : call to implicitly-deleted copy constructor of 'class Ty' |
Here o2
can not be declared by std::move
because Ty
has Tx
class which has deleted move constructor.
For more details about this feature please see this post below,
Implicitly-declared move constructor
The implicitly-declared move constructor in modern C++ is a move constructor that is declared implicitly by using the move constructor of another base class. In other terms you have a new class that uses the base class, this class has implicitly declared a move constructor from the base class.
Let’s give a simple C++ example of an implicitly-declared move constructor which is a move constructor of other base class. Let’s assume that we have Tx
as a base class and we have a new Ty
class. This new class can use the move constructor from the Tx
. Here is a T
x class example with a declared and defined move constructor that uses std::move
,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Tx { public: std::string str; Tx() = default; // Constructor Tx(Tx&& other) // Declared Move Constructor { str = std::move(other.str); } }; |
As given here above, if you have a move constructor, you should define a Constructor too, otherwise you will have “No matching constructor for initialization of class” error in compilation. Now, we can define a new Ty
class and we can use Tx
class as a base class as below.
1 2 3 4 5 6 7 8 9 |
class Ty : public class Tx // uses Tx as a base class { public: void print_str(){ std::cout << str << std::endl; } // This class has Implicitly-declared Move Constructor from Tx class }; |
For more details about this feature please see this post below,
Implicitly-defined move constructor
The Implicitly-defined Move Constructor is a Move Constructor which is implicitly defined by another base, or it is an implicitly-declared move constructor neither deleted nor trivial.
- The Implicitly-defined Move Constructor is defined, which means it has a function body with { } that is generated and compiled by the compiler implicitly.
- The implicitly-defined move constructor performs full move operations on its members if it is a class or struct type.
- The implicitly-defined move constructor copies the object representation (as in std::memmove) if it is a union type.
We can define our own move constructor as shown here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Tx { public: std::string str = "LearnCPlusPlus.org"; Tx() = default; // Constructor Tx(Tx&& other) // Move Constructor Declaration { // Move Constructor Definition str = std::move(other.str); // Move Constructor Definition } // Move Constructor Definition }; |
And, we can use this Tx class as base class to define a new Ty
class as below.
1 2 3 4 5 6 7 8 9 |
class Ty : public class Tx // uses Tx as a base class { public: void print_str(){ std::cout << str << std::endl; } // This class has Implicitly-defined Move Constructor from Tx class }; |
For more details about this feature please see this post below,
Note that this struct can be used in C applications too. As you see, in modern C++, we can easily read WAV wave files, now you can display or edit wave files.
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.
Design. Code. Compile. Deploy.
Start Free Trial
Free C++Builder Community Edition