码迷,mamicode.com
首页 > 其他好文 > 详细

三、资源管理--条款16-17

时间:2018-09-13 16:31:27      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:就是   编译器   nload   down   实现   需要   note   一个   函数   

条款16:成对使用new和delete时要采取相同形式

总结起来就是:

  • new一个数组出来的时候,使用delete []来释放资源。
  • new一个对象出来的时候,使用delete来释放资源。

下面谈谈这样做的本质原因:

new和delete操作

当我们new一个对象的时候,发生两件事:

(1) 内存被分配出来(通过operator new这个函数)。

(2) 一个或多个构造函数被调用。

delete一个对象的时候也是一样:

(1) 一个或多个析构函数被调用。

(2) 内存被释放。(通过operator delete函数)

delete[]是怎么做的

这取决于编译器的实现方式,很多编译器都保存了一个“数组大小”的记录。单一对象和数组对象的内存布局可以看成一下形式:

技术分享图片

如上图所示,对于对象数组,编译器记录了一个数组大小n,随后会调用n次析构函数,并且释放掉这些内存。

作者总结

如果你在new表达式中使用[],必须在相应的delete表达式中也使用[].如果你在new表达式中不使用delete,一定不要在相应的delete表达式中使用[].

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

假设一个场景,我们有以下接口:

int priority(); // 得到一个整数
void processWidget(shared_ptr<Widget> pw,int priority);

现在尝试以如下形式去调用它:

processWidget(shared_ptr<Widget>(new Widget), priority());

这样看来各个参数符合要求,仿佛是一次正确的调用。但这样做却可能导致内存泄漏

我们来分析一下调用此接口前所需要执行的代码。

  • 调用priority函数。
  • 调用new Widget函数。
  • 调用智能指针的构造函数。

但是编译器会以什么样的顺序执行这些代码呢?这是不能够得到预知的,它可能以下面的顺序执行:

(1) 调用new Widget函数。

(2) 调用priority函数。

(3) 调用shared_ptr

当编译器以这种顺序调用时,好巧不巧,第一步调用成功,第二步调用priority时,抛出了一个异常。那么这个时候,new Widget返回的指针并没有置入shared_ptr

基于上述原因,我们应该使用独立的语句将对象置入智能指针中:

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

这样就不会造成内存泄漏问题。

作者总结

以独立语句将newed对象存储入智能指针内。如果不这么做,一旦异常被抛出,有可能导致难以察觉的资源泄漏。

三、资源管理--条款16-17

标签:就是   编译器   nload   down   实现   需要   note   一个   函数   

原文地址:https://www.cnblogs.com/love-jelly-pig/p/9640694.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!