【C++ primer阅读记录】拷贝控制与资源管理

拷贝控制

一般来说对于拷贝我们有两种选择:使类的行为看起来像一个值或者像一个指针。

类的行为像一个值,意味着它有自己的状态。当我们拷贝一个像值的对象时,副本和原对象是完全独立的。

类的对象像指针的话,则为一种共享状态。当我们拷贝一个这种类的对象时,副本和原对象使用相同的底层数据。改变副本也会改变原对象。

行为像值的类

对于类管理的资源,每个对象都应该都一个自己的拷贝。这需要

定义一个拷贝构造函数,完成string的拷贝,而不是拷贝指针

定义一个析构函数释放string

定义一个拷贝赋值运算符来释放当前的string,从右侧运算对象拷贝string

编写拷贝赋值运算符需要记住的:

1)如果将一个值赋予它自身,赋值运算符必须能正确工作。

2)大多数赋值运算符组合了析构函数和拷贝构造函数的工作。

一个好的模式是将右侧运算对象拷贝到一个局部临时对象中,当拷贝完成后,销毁左侧运算对象的现有成员就是安全的了。一旦左侧运算对象的资源被销毁,就只剩下将数据从临时对象拷贝到左侧运算对象的成员中了。

如果自赋自己值的话,不按照规范来。可能会出现先销毁左侧运算对象,备份右侧运算对象的时候发现已经无了。

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
	auto newp = new string(*rhs.ps); //先对右侧赋值参数进行拷贝,newp指向新空间,存储内容和右侧运算										 //值一样
	delete ps; //删除左运算值的数据,释放空间。
	ps = newp; //将newp的地址值交给ps
	return *this;  
	//看起来也可以 ps = new string(*(rhs.ps)) 实际上你需要先释放掉ps的内存空间,如果rhs指向的
    //是自己的话,那就不可以运行了。
}

由于合成析构函数不会使用delete释放指针,因此如果自己不定义析构函数的话,会导致内存泄漏。

如果不定义拷贝构造函数的话,会让两个指针指向同一片空间。

行为像指针的类

定义行为类似指针的类,需要为其定义拷贝构造函数和拷贝赋值函数。

但是析构函数不能单方面地释放关联的string,只有当最后一个指向string和HasPtr被销毁时,才可以释放string。

实际上就需要实现一个类似于shared_ptr来管理类中的资源。我们自己实现的话可以使用引用计数。

为了让多个对象能够管理引用技术,解决方法是将计数器保存在动态内存中。当创建一个对象时,我们也分配一个新的计数器(是指直接初始化的构造函数中分配新计数器吗猜测)。当拷贝或赋值对象时,我们拷贝指向计数器的指针。

练习代码:https://github.com/LeeLinSCUT/C-11_Practice

posted @ 2020-11-28 21:06  LeeSCUT  阅读(88)  评论(0)    收藏  举报