After studying an example for Move Semantics of C++11, I write a more complete code snippet:
#include
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'.