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