Open In App

Move Constructors in C++

Last Updated : 26 Aug, 2025
Comments
Improve
Suggest changes
25 Likes
Like
Report

A move constructor is a special constructor in C++ that lets us transfer the contents of one object to another without copying the data. It is useful for performance - it's faster than copying.

Syntax of Move Constructor in C++

C++
ClassName(ClassName&& other);
  • className&& is an rvalue reference to another object of the same class.
  • The double ampersand && is key: it allows the function to bind to temporary (rvalue) objects.
  • The other object is the source from the resource will be moved, not copied.

Example:

C++
#include <iostream>
using namespace std;

class Geeks {
private:
    int* ptr;

public:
    // Constructor
    Geeks(int value) {
        // Dynamically allocate memory
        ptr = new int(value); 
        cout << "Constructor called\n";
    }

    // Move Constructor
    Geeks(Geeks&& obj) {
        cout << "Move Constructor called\n";
        // Steal the pointer
        ptr = obj.ptr;        
        obj.ptr = nullptr;    
    }

    // Destructor
    ~Geeks() {
        if (ptr != nullptr) {
            cout << "Destructor deleting data: " << *ptr << endl;
        } else {
            cout << "Destructor called on nullptr\n";
        }
        delete ptr;
    }

    // Display function
    void display() {
        if (ptr)
            cout << "Value: " << *ptr << endl;
        else
            cout << "No data\n";
    }
};

int main() {
    // Constructor is called
    Geeks obj1(42);              
    // Move constructor is called
    Geeks obj2 = std::move(obj1); 

    cout << "\nAfter move:\n";
    cout << "obj1: ";
    // Should show "No data"
    obj1.display();              
    cout << "obj2: ";
    // Should show "Value: 42"
    obj2.display();              

    return 0;
}

Output
Constructor called
Move Constructor called

After move:
obj1: No data
obj2: Value: 42
Destructor deleting data: 42
Destructor called on nullptr

Why Move Constructors are Used?

Move constructors are used to transfer resources (like memory or file handles) from one object to another without making a copy, which makes the program faster and more efficient. They're especially useful when working with temporary objects or large data.

Example: Program with Only Copy Constructor and No Move Constructor

C++
// C++ program without declaring the
// move constructor
#include <iostream>
#include <vector>
using namespace std;

// Move Class
class Move {
private:
    // Declaring the raw pointer as
    // the data member of the class
    int* data;

public:
    // Constructor
    Move(int d)
    {
        // Declare object in the heap
        data = new int;
        *data = d;

        cout << "Constructor is called for " << d << endl;
    };

    // Copy Constructor to delegated
    // Copy constructor
    Move(const Move& source)
        : Move{ *source.data }
    {

        // Copying constructor copying
        // the data by making deep copy
        cout << "Copy Constructor is called - "
             << "Deep copy for " << *source.data << endl;
    }

    // Destructor
    ~Move()
    {
        if (data != nullptr)

            // If the pointer is not
            // pointing to nullptr
            cout << "Destructor is called for " << *data
                 << endl;
        else

            // If the pointer is
            // pointing to nullptr
            cout << "Destructor is called"
                 << " for nullptr" << endl;

        // Free the memory assigned to
        // data member of the object
        delete data;
    }
};

// Driver Code
int main()
{
    // Create vector of Move Class
    vector<Move> vec;

    // Inserting object of Move class
    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });
    return 0;
}

Output
Constructor is called for 10
Constructor is called for 10
Copy Constructor is called - Deep copy for 10
Destructor is called for 10
Constructor is called for 20
Constructor is called for 20
Copy Constructor is called - Deep copy for 20
Constructor is called for 10
Copy Constructor is called - Deep copy for 10
Destructor is called for 10
Destructor is called for 20
Destructor is called for 10
Destructor is called for 20

Example: Program with Move Constructor

C++
// C++ program for demonstrating the use of
// move constructor
#include <iostream>
#include <vector>
using namespace std;

// Move Class
class Move {
private:
    // Declare the raw pointer as
    // the data member of class
    int* data;

public:
    // Constructor
    Move(int d)
    {
        // Declare object in the heap
        data = new int;
        *data = d;
        cout << "Constructor is called for " << d << endl;
    };

    // Copy Constructor
    Move(const Move& source)
        : Move{ *source.data }
    {

        // Copying the data by making
        // deep copy
        cout << "Copy Constructor is called -"
             << "Deep copy for " << *source.data << endl;
    }

    // Move Constructor
    Move(Move&& source)
        : data{ source.data }
    {

        cout << "Move Constructor for " << *source.data
             << endl;
        source.data = nullptr;
    }

    // Destructor
    ~Move()
    {
        if (data != nullptr)

            // If pointer is not pointing
            // to nullptr
            cout << "Destructor is called for " << *data
                 << endl;
        else

            // If pointer is pointing
            // to nullptr
            cout << "Destructor is called"
                 << " for nullptr " << endl;

        // Free up the memory assigned to
        // The data member of the object
        delete data;
    }
};

// Driver Code
int main()
{
    // Vector of Move Class
    vector<Move> vec;

    // Inserting Object of Move Class
    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });
    return 0;
}

Output
Constructor is called for 10
Move Constructor for 10
Destructor is called for nullptr 
Constructor is called for 20
Move Constructor for 20
Constructor is called for 10
Copy Constructor is called -Deep copy for 10
Destructor is called for 10
Destructor is called for nullptr 
Destructor is called for 10
Destructor is called for 20

Noexcept Move Constructor

A noexcept move constructor is a move constructor that guarantees it won't throw any exceptions.

Example 1: Without noexcept Move Constructor

C++
// C++ program to illustrate what happens when we
// don't use the noexcept move constructor
#include <bits/stdc++.h>
using namespace std;

class A {
public:
    A() {}
  
    // Move constructor not marked as noexcept
    A(A&& other) {
        cout << "Move constructor" << endl;
    }

    // Copy constructor
    A(const A& other) {
        cout << "Copy constructor" << endl;
    }
};

int main() {
    vector<A> v;

  	// Reserve space for at least two elements to
	// avoid immediate resizing
    v.reserve(2);

    // Uses the move constructor for the temporary objects
    v.push_back(A());
    v.push_back(A());

  	cout << "Resize happens" << endl;
    
    // Move constructor may be called again if resizing occurs
    v.push_back(A());
    
    return 0;
}

Output
Move constructor
Move constructor
Resize happens
Move constructor
Copy constructor
Copy constructor

Example 2: With noexcept Move Constructor

C++
// C++ Program to illustrate the use of
// noexcept move constructor
#include <vector>
#include <iostream>
using namespace std;

class Test {
public:
    Test(){}
      
    // Move constructor marked as noexcept
    Test(Test&& other) noexcept {
        cout << "Move constructor  " << endl;
    }

    // Copy constructor
    Test(const Test& other) {
        cout << "Copy constructor  " << endl;
    }
};

int main() {
    vector<Test> vec;

    vec.reserve(2);  // Reserve space for at least two elements

  Test a;

    vec.push_back(Test());
    vec.push_back(Test());  // Uses the move constructor

    cout << "Resize happens" << endl;
    vec.push_back(Test());
    
    return 0;
}

Output
Move constructor  
Move constructor  
Resize happens
Move constructor  
Move constructor  
Move constructor  

Why use noexcept?

  • It helps the compiler optimize our code, especially with STL containers like std::vector.
  • If a move constructor is not marked noexcept, some STL operations will fall back to slower copy operations to avoid potential exceptions.

Explore