【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来管理类中的资源。我们自己实现的话可以使用引用计数。
为了让多个对象能够管理引用技术,解决方法是将计数器保存在动态内存中。当创建一个对象时,我们也分配一个新的计数器(是指直接初始化的构造函数中分配新计数器吗猜测)。当拷贝或赋值对象时,我们拷贝指向计数器的指针。

浙公网安备 33010602011771号