C++之移动构造函数与拷贝构造函数关系

c++右值引用之转移构造函数文章中,我们介绍了移动构造函数三点注意问题

1、参数(右值)的符号必须是右值引用符号,即“&&”。
2、参数(右值)不可以是常量,因为我们需要修改右值。
3、 参数(右值)的资源链接和标记必须修改。否则,右值的析构函数就会释放资源。转移到新对象的资源也就无效了。

关于第三点原因:虽然调用移动构造函数或者移动赋值操作符后,已经获得了右值的的内存空间,但是之后右值就被销毁了,那么获得的的那片内存也被释放了,指向的就是一个不合法的内存空间。所以我们就要防止这片空间被销毁。

下面有三个问题:

1、没有拷贝构造函数会默认生成移动构造函数吗?
2、有拷贝构造函数还会默认生成移动构造函数吗?
3、有移动构造函数还会默认生成拷贝构造函数吗?

首先看一下代码,简单写了一个类:

#include <iostream>

using namespace std;

class A {
public:
	A(int *ptr = new int) :p(ptr) {}

	/*A(A &a) :p(a.p)
	{
		cout << "调用了拷贝构造函数" << endl;
	}*/
	//A(A &&a) :p(a.p)//本人猜测合成的移动构造函数只完成这一步,而函数体是空的
	//{
	一定要修改指针的指向,这样移动构造就不会析构原对象的成员了
	//	a.p = nullptr;
	//	cout << "调用了移动构造函数呀" << endl;
	//}
	int *p;
};

int main()
{
	//A a1(new int(4));
	A a1;
	A a3;
	A a2(std::move(a1));
	A a4(a3);
	cout << a1.p << endl;
	cout << a3.p << endl;

	system("pause");
	return 0;
}

1、没有拷贝构造函数会默认生成移动构造函数吗?
在这里插入图片描述
看编译结果可知,编译器会自动生成拷贝构造函数和移动构造函数。
但是在默认生成移动构造函数时,未将指针指向NULL,这就有可能出现问题。
默认的移动构造函数不会帮我们把指针成员置空,移后源不是可析构的安全状态,如果这样,当离开移动构造后,源对象被析构,对象内的指针成员空间被回收,转移之后对象内的指针成员出现悬垂现象,程序将引起致命的错误。所以当我们定义了自己的拷贝操作和析构函数时,编译器是不会帮我们合成默认移动构造函数的。这也回答了下一个问题。

2、有拷贝构造函数还会默认生成移动构造函数吗?
把上述代码解除拷贝构造函数的注释就行。
在这里插入图片描述
3、有移动构造函数还会默认生成拷贝构造函数吗?
把上述代码解除移动构造函数的注释就行。
在这里插入图片描述
具体原因还没有查清,望大佬赐教!
也可参考C++Error2208:…尝试引用已删除的函数这篇文章。

一般而言,对象的赋值构造函数如果开发者没有提供,则编译器会生成默认的赋值构造函数。然而,默认的赋值构造函数在以下几种情况会被删除。

该类含有非静态的const成员变量
该类含有非静态的reference成员变量
该类含有不能被拷贝的成员变量
该类含有不能被拷贝的基类
该类含有用户定义的移动构造函数或者移动赋值函数

自己编写的类中有const成员变量, 将其改成static 或者去掉const 或者添加赋值构造函数,就可以消除这个error.

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值