本条款的核心思想只有一句话:那就是在使用智能指针管理对象的时候,一定用一条单独的语句将new出来的对象放入智能指针当中去。
下面举个例子说明一下:
假设有如下的代码:
class Widget
{....};
int priority();//函数1
void processWidget(std::trl::shared_ptr<Widget> pw, int size);//函数2
//调用函数2
processWidget(new Widget, property());
首先这段代码打眼一看没什么问题,其实他连编译都无法通过,因为智能指针shared需要的实参是一个原始指针,并且shared的内部的构造函数的类型是explicit构造函数,意味着不能进行隐式的类型转换,因为实参的类型和形参需要的类型不匹配,而且不能进行隐式转换所以就会编译不通过,将peocessWidghe调用t改成如下就可以了。
processWidget(std::trl::shared_ptr<Widget> (new Widget), property());
但是这样写的话虽然看起来是用智能指针管理的对象,而且编译也通过了,但是同样存在一定的隐患会造成资源泄露,下面我就来抛出这个隐患
首先来剖析如下这个调用语句
processWidget(std::trl::shared_ptr<Widget> (new Widget), property());
1.对于实参中的第一部分会发生两件事
①执行new Widget
②调用tr1::shared_ptr的构造函数
所以整体的这个调用函数中会发生下面三种事情
执行new Widget
调用tr1::shared_ptr的构造函数
调用proprety()函数
首先可以确定的是new Widget肯定在调用tr1::shared_ptr的构造函数之前进行,那么proprety()可以在第一个个调用,可以第二个调用,也可以第三个调用。
加入他们是以这样的顺序调用的
①执行new Widget
②调用proprety()函数
③调用tr1::shared_ptr的构造函数
那么问题就很明显了吧,当②的调用抛出一个异常的时候,new Widget返回的指针将会丢失,因为他还没有被置入智能指针中呢,这样就容易造成资源泄露,这就是我要说的隐患!即资源被创建和资源被转换为资源管理对象之间可能会发生异常的干扰。
所以在将资源放入智能指针中使用的时候,使用单独的语句将资源放进去,不要和任何语句混搭。改写如下
std::trl::shared<Widget> pw(new Widget);//单独的语句
processWidget(pw, property());
这样的话就可以避免产生资源被创建和资源被转换为资源管理对象之间可能会发生异常的干扰的这种问题了!