C++

C++ : Move Constructor

Before reading on the move constructor, read Lvalue and Rvalue

  • The move constructor moves the resources owned by an rvalue object (which does not have a memory address) into an lvalue (at a memory address) without copying.
  • Move constructor is faster than a copy constructor as it does not create a copy of the rvalue object while moving it into an lvalue. Thus a move constructor saves the overhead of copying when multiple temporary objects are pushed into a vector.

    In the below example, when a temporary object of class String is pushed inside a vector using the push_back function, a copy constructor is invoked and executed for creating a copy of the temporary object to be pushed. whereas a move constructor avoids the copy operation.

C++ program for a String class demonstrates the move constuctor.

#include<iostream>
#include<cstring>
#include<vector>

class String {

    private:

    u_int m_len;
    char* m_buff;

    public:

    // Default constructor
    String () {
        std :: cout << "Default constructor of String class got called." << std :: endl;
        m_len = 0;
        m_buff = new char;
        m_buff[0] = '\0';
    }

    // Parameterized constructor
    String (const char * str) {
        std :: cout << "Parameterized constructor of String class got called." << std :: endl;
        m_len = strlen(str);
        m_buff = new char[m_len + 1];
        strcpy(m_buff, str);
    }

    // Copy constructor
    String (const String& obj) {
        std :: cout << "Copy constructor of String class got called." << std :: endl;
        m_len = obj.m_len;
        m_buff = new char[m_len+1];
        strcpy(m_buff, obj.m_buff);
        std :: cout << "Copy constructor will now finish execution" << std :: endl;
    }

    // Move constructor commented
    /*
    String (String&& obj) noexcept {
        std :: cout << "Move constructor of String class got called." << std :: endl;
        m_len = obj.m_len;
        m_buff = obj.m_buff;

        obj.m_len = 0;
        obj.m_buff = nullptr;
        std :: cout << "Move constructor will now finish execution" << std :: endl;
    }*/

    ~String() {
       std :: cout << "Destructor String class got called." << std :: endl;
       if (m_buff) {
           std :: cout << "Deleting the buffer" << std :: endl;
           delete [] m_buff;
       }
    }

    void Display() {
        std :: cout << m_buff << std :: endl;
    }
};

int main() {

   std :: vector<String> vec_String;
   vec_String.push_back(String("Deltoid"));

   std :: cout << "Main ends. Now returning" << std :: endl;
   return 0;
}

Output

Parameterized constructor of String class got called.
Copy constructor of String class got called.
Copy constructor will now finish execution
Destructor String class got called.
Deleting the buffer
Main ends. Now returning
Destructor String class got called.
Deleting the buffer
#include<iostream>
#include<cstring>
#include<vector>

class String {

    private:

    u_int m_len;
    char* m_buff;

    public:

    // Default constructor
    String () {
        std :: cout << "Default constructor of String class got called." << std :: endl;
        m_len = 0;
        m_buff = new char;
        m_buff[0] = '\0';
    }

    // Parameterized constructor
    String (const char * str) {
        std :: cout << "Parameterized constructor of String class got called." << std :: endl;
        m_len = strlen(str);
        m_buff = new char[m_len + 1];
        strcpy(m_buff, str);
    }

    // Copy constructor
    String (const String& obj) {
        std :: cout << "Copy constructor of String class got called." << std :: endl;
        m_len = obj.m_len;
        m_buff = new char[m_len+1];
        strcpy(m_buff, obj.m_buff);
        std :: cout << "Copy constructor will now finish execution" << std :: endl;
    }

    // Move constructor
    String (String&& obj) noexcept {
        std :: cout << "Move constructor of String class got called." << std :: endl;
        m_len = obj.m_len;
        m_buff = obj.m_buff;

        obj.m_len = 0;
        obj.m_buff = nullptr;
        std :: cout << "Move constructor will now finish execution" << std :: endl;
    }

    ~String() {
       std :: cout << "Destructor String class got called." << std :: endl;
       if (m_buff) {
           std :: cout << "Deleting the buffer" << std :: endl;
           delete [] m_buff;
       }
    }

    void Display() {
        std :: cout << m_buff << std :: endl;
    }
};

int main() {

   std :: vector<String> vec_String;
   vec_String.push_back(String("Deltoid"));

   std :: cout << "Main ends. Now returning" << std :: endl;
   return 0;
}

Output

Parameterized constructor of String class got called.
Move constructor of String class got called.
Move constructor will now finish execution
Destructor String class got called.
Main ends. Now returning
Destructor String class got called.
Deleting the buffer


Copyright (c) 2019-2023, Algotree.org.
All rights reserved.