我认为编译器合成的移动构造函数只完成成员的移动,而不会把指针成员置空,eg:
先不定义移动构造函数,使用编译器合成的移动构造。
- #include <iostream>
- using namespace std;
- class A{
- public:
- A(int *ptr=new int):p(ptr){}
- int *p;
- };
- int main()
- {
- A a1(new int(4));
- A a2(std::move(a1));
- cout<<a1.p<<endl;
- return 0;
- }
结果
说明编译器没有把成员指针p置空。
再看我们自己定义的移动构造函数:
- class A{
- public:
- A(int *ptr=new int):p(ptr){}
- A(A &&a):p(a.p)//本人猜测合成的移动构造函数只完成这一步,而函数体是空的
- {
- a.p=nullptr;
- }
- int *p;
- };
同上main函数,执行结果:
同时从这里我们也可以隐隐推断,为甚我们定义了自己的拷贝构造,拷贝赋值运算符,析构函数后,编译器不会帮我们合成移动构造函数,因为,如果我们定义了这些操作往往表示类内含有指针成员需要动态分配内存,如果需要为类定义移动操作,那么应该确保移动后源对象是安全的,但是默认的移动构造函数不会帮我们把指针成员置空,移后源不是可析构的安全状态,如果这样,当离开移动构造后,源对象被析构,对象内的指针成员空间被回收,转移之后对象内的指针成员出现悬垂现象,程序将引起致命的错误。所以当我们定义了自己的拷贝操作和析构函数时,编译器是不会帮我们合成默认移动构造函数的。
FROM: http://blog.youkuaiyun.com/zzyafyj/article/details/38686617