#include<iostream>
using namespace std;
class HasPtrMem {
public:
HasPtrMem() :d(new int(0)) {
cout << "Construct : "<<++n_cstr << endl;
}
/*HasPtrMem(const HasPtrMem& h) :d(h.d) { //最常规的拷贝构造,执行的是浅拷贝
cout << "Copy Construct_1: " << ++n_cpst << endl;
}*/
HasPtrMem(const HasPtrMem& h) :d(new int(*h.d)) {
cout << "Copy Construct_2: " << ++n_cpst << endl;
}
//HasPtrMem( HasPtrMem&& h) :d(h.d) {
// h.d = nullptr;
// cout << "Move Construct " << ++n_mvtr << endl;
//}
~HasPtrMem() {
delete d;
cout << "Destruct "<<++n_dstr << endl;
}
int* d;
static int n_cstr;
static int n_cpst;
static int n_mvtr;
static int n_dstr;
};
int HasPtrMem::n_cstr = 0;
int HasPtrMem::n_cpst = 0;
int HasPtrMem::n_mvtr = 0;
int HasPtrMem::n_dstr = 0;
HasPtrMem GetTemp() {
HasPtrMem h;
cout << "Resource from " << __func__ << ":" << hex << h.d << endl;
return h;
}
int main() {
/*
没有Move 构造函数,则调用自定义的Copy 构造函数,若没有copy构造 函数,
则 调用默认copy构造函数
析构时候导致同一段内存被析构两次,程序崩溃
第二:
程序员通常还会为声明了移动构造函数的类,
还会声明一个常量左值为参数的拷贝构造函数,确保移动不成还可以拷贝
常量左值引用是万能的,
常量右值引用到现在没啥用
移动语义需要右值是能被修改的,所以都是非常量的右值引用
*/
HasPtrMem a = GetTemp();
cout << "Resuource from " << __func__<<":" << hex << a.d << endl;
}
#include<iostream>
using namespace std;
class Moveable {
public:
Moveable() : i(new int(3)) { cout << "默认构造" << endl; }
~Moveable() { delete i; cout << "析构" << endl; }
Moveable(const Moveable& m) :i(m.i) { cout<<"拷贝构造1."<<endl; }
Moveable(const Moveable& m) : i(new int(*m.i)) { cout<<"拷贝构造2,确保move失败至少能够拷贝构造"<<endl; }
//Moveable(Moveable&& m) : i(m.i) {
// m.i = nullptr;
// cout << "移动构造" << endl;
//}
int* i;
};
int main() {
Moveable a;
Moveable c(move(a)); //调用移动构造函数
cout << *a.i << endl;//若成功调用移动构造,则a.i已被置空,再解引用必定报错
}
参考书籍:深入理解C++11 P75