After studying an example for Move Semantics of C++11, I write a more complete code snippet:
#include <iostream> using namespace std; class Intvec { public: explicit Intvec(size_t num = 0) : m_size(num), m_data(new int[m_size]) { log("constructor"); } ~Intvec() { log("destructor"); if (m_data) { delete[] m_data; m_data = 0; } } Intvec(const Intvec& other) : m_size(other.m_size), m_data(new int[m_size]) { log("copy constructor"); for (size_t i = 0; i < m_size; ++i) m_data[i] = other.m_data[i]; } Intvec(Intvec&& other) { log("move constructor"); std::swap(m_size, other.m_size); std::swap(m_data, other.m_data); other.m_size = 0; other.m_data = nullptr; } Intvec& operator=(const Intvec& other) { log("copy assignment operator"); Intvec tmp(other); std::swap(m_size, tmp.m_size); std::swap(m_data, tmp.m_data); return *this; } Intvec& operator=(Intvec&& other) { log("move assignment operator"); std::swap(m_size, other.m_size); std::swap(m_data, other.m_data); return *this; } private: void log(const char* msg) { cout << "[" << this << "] " << msg << "\n"; } size_t m_size; int* m_data; }; int main(void) { Intvec v1(20); Intvec v2; cout << "assigning lvalue...\n"; v2 = v1; cout << "ended assigning lvalue...\n"; //Intvec v4 = std::move(Intvec(30)); Intvec v3; cout << "move assigning...\n"; v3 = Intvec(30); cout << "ended move assigning...\n"; cout << "move constructor\n"; Intvec v4 = std::move(v3); cout << "ended move constructor\n"; return 0; }
Pay attention to last two lines in ‘move constructor’:
... other.m_size = 0; other.m_data = nullptr; ...
Since ‘move constructor’ will not set initial value for m_size and m_data of ‘v4’, the m_size and m_data of ‘v3’ will be uninitial after swaps. Adding the two lines of code means to initialize m_size and m_data of ‘v3’.