条款17:以独立语句将newed对象置入智能指针

目录

1.引言

2.分析

2.1编译不通过原理

2.2解决方法


1.引言

有这样一个函数,用来揭示程序处理的优先权。另一个函数用来在某动态分配得到的Widget上进行某些带有优先权的处理:

int priority();
void processWidget(std::trl::shared_ptr<Widget> pw,int priority);//依据”以对象管理资源“的原则,决定对动态分配的来的Widget运用智能指针,这里采用trl::shared_ptr

现在考虑调用processWidget:

processWidget(new Widget,priority());

该调用形式其实不能通过编译。因为trl::shared_ptr构造函数需要一个原始指针(raw pointer),但是该构造函数是个explicit构造函数无法进行隐式转换,将得自"new Widget"的原始指针转换为processWidget所要求的trl::shared_ptr。

​​​要想通过编译,写成如下形式:

processWidget(std::trl::shared_ptr<Widget>(new Widget),priority());

虽然这样能顺利通过编译,并且使用了”以对象管理资源“,但这样调用却可能出现资源泄露。具体原因在下节将进行分析。

2.分析

2.1编译不通过原理

编译器生成一个processWidget调用码之前,首先会核算即将被传递的各个实参。processWidget的第二个实参只是一个单纯的对priority函数的调用,但第一个实参std::trl::shared_ptr<Widget>(new Widget)由两部分组成:

                1.执行"new Widget"表达式

                2.调用trl::shared_ptr构造函数

于是在调用processWIdget之前,编译器必须创建代码,需要做以下三件事:

                1.调用priority

                2.执行"new Widget"

                3.调用trl::shared_ptr构造函数

但这里存在一个问题,即C++编译器会以什么样的次序完成这些事情呢?这里可以确定的是"new Widget"一定执行于trl::shared_ptr构造函数被调用之前,因为这个表达式的结果还要被传递作为trl::shared_ptr构造函数的一个实参,但是对priority的调用则可以排在第一或第二或第三执行。

假设编译器选择以第二顺位执行它,最终的操作顺序如下:

                        1.执行”new Widget“

                        2.调用priority

                        3.调用trl::shared_ptr构造函数

倘若在这个过程中,对priority的调用导致异常,会发生什么事情呢?在这种情况下”new Widget“返回的指针将会遗失。因为它还未执行第三步,尚未被置入trl::shared_ptr内,而该步是用来防止资源泄露的武器。正因为如此,在对processWidget的调用过程中,可能会引发资源泄露。因为在资源被创建(由new Widget)和资源被转换为资源管理对象这两个事件点之间可能发生异常干扰。

2.2解决方法

避免这类方法其实很简单:

  1. 创建Widget
  2. 将它置入一个智能指针内,然后将那个智能指针传给processWidget;
std::trl::shared_ptr<Widget> pw(new Widget);//以智能指针存储newed所得的对象作为一条单独的语句
processWidget(pw,priority());//这个调用动作不会造成资源泄露

以上之所以行得通,因为编译器都是一步一步按照编写顺序对代码进行执行,不会跨越语句进行各项操作。在上述的代码中,"new Widget"及对"trl::shared_ptr"构造函数的调用操作这两个动作和对"priority函数的调用"是分开来的,即执行顺序已经被确定了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值