C++ is packed with Object Oriented Programming features, such as Classes, Objects, constructors, move constructors, destructors, etc. Since the C++11 standard, in a modern C++ compiler, one of the features is the move constructor that allows you to move the resources from one object to another object without copying them. One of the move constructors is the Deleted Implicitly-declared Move Constructor (also it is shown in compiler errors as Implicitly-deleted Move Constructor) which is deleted in a base class directly or has been deleted because of some other declarations,. In this post, we explain the implicitly-declared move Constructor in Modern C++.
First, let’s remind ourselves what are classes and objects in C++.
Table of Contents
What are classes and objects in modern C++?
Classes are defined in C++ using keyword class
followed by the name of the class. Classes are the blueprint for the objects and they are user-defined data types that we can use in our program, and they work as an object constructor. Objects are an instantiation of a class, In another term. In C++ programming, most of the commands are associated with classes and objects, along with their attributes and methods. Here is a simple class example.
1 2 3 4 5 6 7 |
class Tmyclass { public: std::string str; }; |
Then we can create our objects with this Type of myclass like so:
1 2 3 |
Tmyclass o1, o2; |
What is a move constructor in modern C++?
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 is used to move data of one object to the new one. It effectively makes a new pointer to the members of an old object and transfers the resources to the heap memory. When you move a member, if the data member is a pointer, you should also set the value of the member of the old object to a NULL value. When you use the move constructor, you don’t use unnecessary data copying in memory. This allows you to create objects faster. Mostly, if your class/object has a move constructor, you can use other move methods of other features of C++, for example, std::vector
, std::array
, std::map
, etc. You can create a vector with your class type then you can use the push_back()
method that runs your move constructor.
Here is the most common syntax for the move constructor in C++ (Since C++11).
1 2 3 |
class_name ( class_name && ) |
This general syntax is also a syntax for the “Typical declaration of a move constructor”.
1 2 3 4 5 |
class_name ( class_name && ) // Declaration { // Definition } // Definition |
What is a deleted implicitly-declared move constructor in C++?
The Deleted Implicitly-declared Move Constructor (also known in compiler errors as the implicitly-deleted move constructor) is a Move Constructor which is deleted in a base class directly or has been deleted because of some other declarations.
In modern C++, the implicitly-deleted move constructor for class type T
is defined as deleted if this class type T
:
- has non-static data members that cannot be moved, or
- has direct or virtual base class that cannot be moved, or
- has direct or virtual base class or a non-static data member with a deleted or inaccessible destructor, or
- is a union-like class and has a variant member with non-trivial move constructor
If there is a defaulted move constructor that is deleted, then it is ignored by overload resolution, because in other case it will prevent copy-initialization from rvalue.
In C++, The Rule of Five states that if a type ever needs one of the following special members, then it must have all of the five special members.
- copy constructor
- copy assignment
- move constructor
- move assignment
- destructor
In other words, if you have a move constructor in a class, you should carefully define all of these in accordance with your data members (properties).
Note that, classes may have different move constructors. Additionally, if there is a user-defined move constructor present, the user may still delete the implicitly declared move constructor with the keyword delete
.
Is there a simple example of a deleted implicitly-declared move constructor in C++?
Let’s give a simple C++ example of a deleted implicitly-declared move constructor which is a move constructor of another base class. Let’s assume that we have Tx
as a base class, and we have a new Ty
class.
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 |
class Tx { public: std::string str; Tx() = default; // Constructor Tx(Tx&& other) = delete; // Deleted Move Constructor }; |
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-deleted Move Constructor from Tx class }; |
As you can see, 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.
Is there a full example of a deleted implicitly-declared move constructor in modern C++?
Here is a full example of a default (forced) move constructor, where one object is moved to another one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <iostream> #include <string> class Tx { public: std::string str = "LearnCPlusPlus.org"; Tx() = default; // Constructor Tx(Tx&& other) = delete; // Deleted Move Constructor }; class Ty : public Tx // uses Tx as a base class { public: void print_str(){ std::cout << str << std::endl; } // This class has implicitly-deleted default constructor from Tx class }; int main() { class Ty o1; o1.print_str(); // class Ty o2 = std::move(o1); // ERROR : call to implicitly-deleted copy constructor of 'class Ty' system("pause"); return 0; } |
If you remove the last commented line, you will see this error below,
1 2 3 4 5 |
ERROR : call to implicitly-deleted copy constructor of 'class Ty' Press any key to continue . . . |
Is there a move constructor in a simple class, how can I delete it?
Note that, a simple empty C++ class is perfectly equivalent to default implementations (Rule of Five) in a class. A modern compiler is able to provide all these special member functions (default implementations). In example, this simple class below,
1 2 3 4 5 6 |
class Tx { }; |
is exactly the same as the one below in modern C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Tx { public: Tx() = default; // constructor Tx(Tx const& other) = default; // copy constructor Tx& operator=(Tx const& other) = default; // copy assignment operator Tx(Tx&& other) = default; // move constructor Tx& operator=(Tx&& other) = default; // move assignment operator ~Tx() = default; // destructor }; |
If you don’t want this move constructer to be used in your objects, in other words you don’t want your objects to be moved, then you should delete it while the other special functions are in default as below,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Tx { public: Tx() = default; // constructor Tx(Tx const& other) = default; // copy constructor Tx& operator=(Tx const& other) = default; // copy assignment operator Tx(Tx&& other) = default; // move constructor Tx& operator=(Tx&& other) = delete; // deleted move assignment operator ~Tx() = default; // destructor }; |
If you need more technical details about the move constructor, it is explained by Bjarne Stroustrup and Lawrence Crowlcan in this publication here; https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html
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.