C++Primer 13章学习笔-三/五法则

三/五法则

什么是三法则

如果需要析构函数,则一定需要拷贝构造函数和拷贝赋值操作符。

什么是五法则

在较新的 C++11 标准中,为了支持移动语义,又增加了移动构造函数和移动赋值运算符,这样共有五个特殊的成员函数,所以又称为“C++五法则”;

如果需要析构函数,则一定需要拷贝构造函数和拷贝赋值操作符。

原因:

类中出现了指针类型的成员。有指针类型的成员,我们必须防止浅拷贝问题,所以,一定需要拷贝构造函数和赋值操作符,这两个函数是防止浅拷贝问题所必须的。

一个对象拥有额外的资源(指针指向的内存),但另一个对象使用合成的拷贝构造函数也同时拥有这块资源。当一方对象被销毁后,析构函数释放了资源,这时另一个对象便失去了这块资源(但程序员还不知道)。

class HasPtr
{
public:
	HasPtr(const std::string& s = std::string()) :ps(new std::string(s)), i(0) {}

	//HasPtr(const HasPtr& hasPtr);
	//HasPtr& operator=(const HasPtr& hasPtr);
	~HasPtr() { delete ps; };
private:
	std::string* ps;
	int i;
};
HasPtr f(HasPtr hp) // 使用了合成拷贝构造函数,使得hp.ps 和 p.ps 指向相同内存
{
	HasPtr ret = hp; // 使用了合成拷贝构造函数,使得ret.ps 和 hp.ps 指向相同内存
	return ret; // retrurn 之后,ret和hp 会被释放资源,调用析构函数 析构函数会delete ps 导致p.ps 的内存被释放。
}

	HasPtr p("some value");
	f(p); // 当f结束时,p.ps 指向的内存被释放
	HasPtr q(p); // p和q都指向无效内存

如果一个类需要自定义析构函数,几乎可以肯定它也需要自定义拷贝赋值运算符和拷贝运算符

需要拷贝操作的类也需要赋值操作,反之亦然,但不一定意味着需要析构函数

与三之法则不同的是,不提供移动构造函数和移动赋值运算符通常不是错误,但会导致失去优化机会。


2023.6.22 补充说明

如果一个类存在const成员 -> 则不能使用合成的拷贝赋值操作。

如果一个类中存在引用成员 -> 则不能使用合成的拷贝赋值操作,且默认构造函数也是被删除的。|

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值