Trusted answers to developer questions

What is a move constructor in C++?

Free System Design Interview Course

Many candidates are rejected or down-leveled due to poor performance in their System Design Interview. Stand out in System Design Interviews and get hired in 2024 with this popular free course.

A move constructor allows the resources owned by an rvalue object to be moved into an lvalue without creating its copy.

An rvalue is an expression that does not have any memory address, and an lvalue is an expression with a memory address.

What is an Rvalue reference?

Before jumping on to the rvalue reference, let’s see one of the limitations in C++:

int &j = 20;

The above code snippet will give an error because, in C++, a variable cannot be referenced to a temporary object. The correct way to do it is to create an​ rvalue reference using && :

int &&j = 20;

Temporary objects are often created during the execution of a C++ program.

The best usage of an rvalue reference can be seen in the move constructor.

#include <iostream>
#include <vector>
using namespace std;
class A{
int *ptr;
public:
A(){
// Default constructor
cout << "Calling Default constructor\n";
ptr = new int ;
}
A( const A & obj){
// Copy Constructor
// copy of object is created
this->ptr = new int;
// Deep copying
cout << "Calling Copy constructor\n";
}
~A(){
// Destructor
cout << "Calling Destructor\n";
delete ptr;
}
};
int main() {
vector <A> vec;
vec.push_back(A());
return 0;
}

Now, when the above code is executed, the default constructor is called at the time that the temporary object A is created. The copy constructor is called as the temporary object of A is pushed back in the vector.

In the above code, there is a serious performance overhead as the temporary object A is first created in the default constructor and then in the copy constructor. The move constructor is used to avoid this performance overhead:

#include <iostream>
#include <vector>
using namespace std;
class A{
int *ptr;
public:
A(){
// Default constructor
cout << "Calling Default constructor\n";
ptr = new int ;
}
A( const A & obj){
// Copy Constructor
// copy of object is created
this->ptr = new int;
// Deep copying
cout << "Calling Copy constructor\n";
}
A ( A && obj){
// Move constructor
// It will simply shift the resources,
// without creating a copy.
cout << "Calling Move constructor\n";
this->ptr = obj.ptr;
obj.ptr = NULL;
}
~A(){
// Destructor
cout << "Calling Destructor\n";
delete ptr;
}
};
int main() {
vector <A> vec;
vec.push_back(A());
return 0;
}

When the above code is executed, the move constructor is called instead of the copy constructor. With the move constructor, the copy of the temporary object of A is avoided. For a large number of push_back statements, using the move constructor is an efficient choice.

Note: a move constructor can be explicitly called, with the move() function, ​for already created objects.

RELATED TAGS

constructors
c++
Copyright ©2024 Educative, Inc. All rights reserved
Did you find this helpful?