Effective C++ 学习笔记 《十七》

Item 17 Store new ed objects in smart pointers in standalone statements.

其实这一点讲的要点比较隐晦,在平时编程的时候很难发现这个问题,但要是不注意却又是一个隐患,所以对这个要点的理解更应该养成是一种编程习惯。

首先书上给了一段代码作为例子

int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);

这个priority()函数是计算优先级的,就比如是操作系统中进程的优先级,然后下面的processWidget函数是一个处理函数,这个处理函数中第一个参数用到了一个智能指针,这个智能指针是用来管理动态分配的一个Widget,另一个参数是优先级。

现在考虑这样来调用这个函数

processWidget(new Widget, priority());

但是 这样是通过不了编译的,原因在于智能指针的构造函数中,利用它指向的元素类型(raw type 这里就是Widget)来构造的函数是explicit的,这就意味着不能进行隐式转换,解释一下:
按照原本的想法,应该是先new Widget得到一个指向Widget的指针Widget*,然后用这个指针去构造shared_ptr< Widget > pw, 显然要进行一个类型转换,但是问题就是这个构造函数是explicit修饰的,explicit的意义是在编译阶段就阻止进行隐式转换,所以无法通过编译,那怎么来解决这个问题呢?
很简单,写成这样就可以了

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

也就是在调用的时候写一个类型转换,就能通过编译。

但是就是这样一种写法,也会带来内存泄漏的隐患,这也是item17想强调的地方

来分析一下这种写法到底发生了什么,首先它的参数中,肯定是有这样的三个过程要进行:

  • new Widget
  • std::tr1::shared_ptr< Widget >( new Widget)
  • priority()

这三个过程是在一个函数调用中发生的,在C++中没有规定这三个过程的发生顺序,也就意味着可以有这样的一种发生顺序:

1.new Widget
2.priority()
3. std::tr1::shared_ptr< Widget >( new Widget)

如果按照这样的顺序进行操作,那么在进行到第二步priority()时,如果发生了异常,那么后面的第三步就不会再执行,而第三步是对动态分配内存管理的至关重要的方法(在item13中强调过),这样就导致我们会丢失对new产生的内存的泄漏。
那么如何来解决这个问题呢?书上的建议就是把过程1和3与过程2分离开来,具体来说就是

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

这样第一句完成new Widget的过程,同时把它进行类型转换,放进智能指针管理,然后再调用process函数进行处理,这样写成两句代码的形式就避免了内存泄漏的问题。这也就是item17强调的点 Store new ed objects in smart pointers in standalone statements(在一个单独的语句中把new创建的对象存进智能指针)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值