Move Assignment Operator explained with simple example

In C++11 (Introduction to C++11) , move assignment operator are added which can improve any code’s performance drastically. Typically a move assignment operator is same as copy/move constructor but before reusing the memory blocks from passed object, it releases all the memory which is owned by this object. Since, memory reallocation is avoided in case of move assignment operators. Thus it gives better performance.

However while implementing move assignment operators we need to take care of one important point to ensure that the original object can be correctly destroyed.

Let’s take an example to see how this memory reallocation is avoided in case of move assignment.

#include <iostream>
#include <string.h>
#include <time.h>
#include <chrono>

class MoveHelper
{
private:
    int length;
    char* data;

public:
    // Normal Constructor
    MoveHelper(int length, char* sampleData) : length(length)
    {
        cout << "Inside MoveHelper constructor" << endl;
        data = new char[(strlen(sampleData))];
        copy(sampleData, (sampleData + strlen(sampleData)), data);
    }

    //Copy Constructor
    MoveHelper(const MoveHelper& copy)
    {
        cout << "Inside MoveHelper copy constructor" << endl;
        length = copy.length;
        data = new char[(strlen(copy.data))];
        std::copy(copy.data, (copy.data + strlen(copy.data)), data);
    }

    //Move Constructor
    MoveHelper(MoveHelper&& copy)
    {
        cout << "Inside MoveHelper move constructor" << endl;
        length = copy.length;
        data = copy.data;
        copy.data = NULL;
    }

    //Assignment operator
    MoveHelper& operator=(const MoveHelper & copy)
    {
        cout << "Inside assignment operator" << endl;
        delete[] data;
        length = copy.length;
        data = new char[(strlen(copy.data))];
        std::copy(copy.data, (copy.data + strlen(copy.data)), data);
        return *this;
    }

    //Move Assignment operator
    MoveHelper& operator=(MoveHelper && copy)
    {
        cout << "Inside Move assignment operator" << endl;
        delete[] data;
        length = copy.length;
        data = copy.data;
        copy.data = NULL;
        return *this;
    }

    //destructor
    ~MoveHelper()
    {
        cout << "Inside MoveHelper destructor" << endl;
        delete[] data;
    }
};

int main()
{
    MoveHelper mv1(strlen("Hello1234567"), "Hello1234567");
    MoveHelper mv2(mv1); //Copy constructor called
    MoveHelper mv3(move(mv1)); // Move constructor called. After this "mv1" will become useless so don't use this object after this.

    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    mv1 = mv2;
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    mv2 = std::move(mv3);
    high_resolution_clock::time_point t3 = high_resolution_clock::now();

    auto duration1 = duration_cast<microseconds>(t2 - t1).count();
    auto duration2 = duration_cast<microseconds>(t3 - t2).count();

    cout << "Object created via assignment constructor execution time: " << duration1 << endl;
    cout << "Object created via Move assignment operator execution time: " << duration2 << endl;
}

As shown in above example, normal assignment operator is doing deep copy where as move assignment operator is simply stole the memory from passed object to avoid reallocation of memory.

Execution time of these constructors will confirm that move constructor is indeed provide better performance.

Output of above program:

Inside MoveHelper constructor
Inside MoveHelper copy constructor
Inside MoveHelper move constructor
Inside assignment operator
Inside Move assignment operator
Object created via assignment constructor execution time: 1248
Object created via Move assignment operator execution time: 1017
Inside MoveHelper destructor
Inside MoveHelper destructor
Inside MoveHelper destructor

 

Leave a Reply

Your email address will not be published. Required fields are marked *