对于智能指针我博客中C++部分有关于它的介绍,不知道的可以去看看。
下面我来总结一下
条款12:以对象来管理资源
这个条款其实就是告诉我们用智能指针来管理对象(顺便就管理对象中的资源了),在这一条款种引用了最基本的两个智能指针auto_ptr(资源转移)和shared_ptr(引用计数)。
下面我来总结一下文中的内容
1.为什么要用智能指针来管理资源呢?
解释如下:
假设有如下代码:简化版的函数能说明问题就好了
class Investment
{
//..里面有若干功能和资源
};
Investment* createInvestment()//工厂模式,提供特定的对象
{
//制造一个Inverstment对象返回去,不过这里用的是指向对象的指针
}
//现在有这么一个f函数
void f()
{
Investment *pInv = createInvestment();//启动工厂得到对象(调用这个函数产生对象)
//....中间有若干操作
delete pInv;
}
在这里f函数调用了工厂函数得到了一个函数,所以他就有义务去删除它。这个函数正常情况下看起来没什么问题,但是也有若干情况下f无法删除它得自工厂产生的对象,因为“//....中间有若干操作”有太多的情况导致这个结果,比如1.delete之前有个return,2.或者这个体系在一个循环中突然的一个continue或者goto的出现3.或者在delete之前发生异常...等等一系列的问题反正最终都会导致无法delete无法正常释放。这是一个很严重的问题,因为内存泄漏的仅仅是那块内存,更重要的是内存中的信息。
虽然谨慎会防止这些问题的发生,但是在谨慎随着一系列的变化单单依靠f来执行delete是不够安全的,所以就用智能指针来保存资源利用析构函数自动调用机制确保不会有任何失误。
首先想到的是auto_ptr,所以将f函数改成如下
void f()
{
std::auto_ptr<Investment> pInv(createInvestment());//这样的话就把对象交给了智能指针保管
}
这样的话在确保了Invertment对象的正常释放。
注意条款种黑体字:1.获得对象后立即放进管理对象:上面的代码便实现了这句话。实际上“以对象管理资源”的概念常常被称为“资源取得时机便是初始化时机”因为我们总是在得到一个对象以后在同一条语句中用它来初始化某个管理对象。有时候获得的对象资源被用来赋值某个管理对象,但不论哪种做法,每一个对象在出生的时候就被放进了管理资源种。
2:管理对象运用析构函数,确保资源被释放:不论控制流如何离开区块,一旦当前对象离开作用域其析构函数会被自动调用,于是他管理的对象就会被释放。如果资源管理的析构抛出了异常...会有些麻烦,不过...前面我已经说过了绝不在析构函数种抛出异常,自己看以去看条款指针这块怎么解释的们这里就不多说了。
上面的auto_ptr指针虽然解决了内存泄露问题,但是他也很多的缺点。
1.最开始的缺点是不能让一个auto_ptr管理多个对象,因为会重复释放一块空间多次,会产生未定义的行为,
2.虽然1问题被解决了但是他解决后又有新问题了,那就是如果用拷贝构构造函数或者赋值运算符重载函数赋值他们的话,被复制的那个管理者就会指向空,而新产生的那个版本就会拥有资源管理的唯一权限。(这就是我最开始写的的权限转移的解释)
所以从上面的缺点来看auto_ptr不是管理资源的利器,再者STL容器都不愿被他管理。所以代替auto_ptr的代替版本就出来了--->"引用计数型智能指针“也就是shared_ptr
不过他的缺陷是会陷入循环引用。
注意:auto_ptr和shared_ptr都是在其析构函数种delete动作而不是delete[]
本条款的核心思想就是告诉你用智能指针管理资源,从而提出了两个智能指针。
条款:14在资源管理中心小心copy行为
上面发现我说的太罗嗦了,所以后文就只总结重点
1.在使用智能指针尽量防止智能指针之间的复制拷贝,如果不能的话继续看下面
2.如果不能的话可以进行资源转移方案
3.再不行使用引用计数,保证只有最后一个管理者去销毁的时候在释放它不过记得在拷贝的过程使用深拷贝,保证每个资源都被完整的转移
条款:15在资源管理类中提供对原始资源的访问
1.智能指针也是指针,需要直接使用管理对象去访问你管理的资源。
方法1.重载* ->等运算符
方法2 .或者在管理者设定一个返回原始指针的方法
方法3,显示转换函数(百度了解)
上面的1,2都是隐式转换,3是显示转换
隐式转换的缺点:
1.如果我要复制智能指针的话不经意间右值进行了隐式转换,降级为了原始指针,这样岂不是容易会出错(好比一块资源被两个对象管理)
所以我们该使用如何取决使用哪种方式的是转化?
这个取决于你具体想让你设计的智能指针来干什么,显示一般来说是更好的选择,但是你可能觉得这样违背了类的封装性,但是智能指针又不是为了封装而存在的,他是用来管理资源的,所以这个不矛盾。
总结这三个条款:13:引入智能指针来管理资源这个概念
14,15:更多的是告诉我们如何设计自己更好的智能指针的建议。
至于详细的解释智能指针可以看我的这篇博客