问题聚焦:
    我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展。
    对于单一对象和对象数组,我们要分开考虑
    遇到typedef时,也需要搞清楚,是单一对象类型还是对象数组类型
 

来看一个例子:
std::string* stringArray = new std::string[100];
...
delete stringArray;
问题:stringArray所含的100个string对象中的99个可能并没有被适当地删除,因为它们的析构函数很可能没有被调用。

我们来了解一下,使用new时发生了什么,一共有两个动作:
  1. 内存被分配出来
  2. 针对此内存会有一个或更多个构造函数被调用
使用delete,也有两个动作:
  1. 针对此内存会有一个或更多个析构函数被调用
  2. 内存被释放
简单地说就是:
    即将被删除的那个指针,所指的是单一对象,还是对象数组。

内存分布:单一对象和对象数组的内存分布
    
正如上图所示,数组所用的内存往往还包括“数组大小”的记录,以便delete知道需要调用多少次析构函数。
当对着一个指针使用delete,唯一能够让它知道当前是删除单一对象还是对象数组的方法就是,由你来告诉它。
如下面这样:
std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];
...
delete stringPtr1;
delete[] stringPtr2;
如果对stringP1使用delete[] 这种形式,结果也不一定让人愉快,因为它读取的数组大小显然是错误的。
那我们应该怎么办呢?解决方案很简单:
如果你调用new时,使用new[] 的形式,那么对应调用delete时也使用[],
如果你调用delete时,没有使用new[] 的形式,那么对应调用delete时也不应该使用[] 形式。
当你设计的class含有一个指针指向动态分配内存,并提供多个构造函数时,上述的规则尤为重要。
这时,你需要小心地在所有构造函数中使用相同形式的new将指针成员初始化,同时,相应的析构函数也要使用相同的形式。

当使用typedef时,要变得尤为敏感,因为你必须要明确地知道,这时的new是一个什么样的形式:
typedef std::string AddressLines[4];       // 每个人的地址有4行,每行是一个string

// 这时候AddresLines是一个数组,所以new时,应该是[]形式
std:string* pal = new AddresLines; // 相当于:new string[4];
//那么,必须匹配数组形式的delete
delete pal; // error,行为未定义
delete[] pal; // pass
所以,最好尽量不要对数组形式使用typedef动作。

小结:
  • 如果在new表达式中使用[],必须在相应的delete表达式中也使用[]
  • 如果在new表达式中不使用[],一定不要再相应的delete表达式中使用[]
  • 尽量不要对对象数组使用typedef动作
参考资料:
《Effective C++ 3rd》

Effective C++(16) 成对使用new和delete时要采取相同的形式的更多相关文章

  1. 读书笔记 effective c++ Item 16 成对使用new和delete时要用相同的形式

    1. 一个错误释放内存的例子 下面的场景会有什么错? std::]; ... delete stringArray 一切看上去都是有序的.new匹配了一个delete.但有一些地方确实是错了.程序的行 ...

  2. 条款16:成对使用new和delete时,采取相同的形式

    问题聚焦:     我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展.     对于单一对象和对象数组,我们要分开考虑.     遇到typedef时,也需要搞 ...

  3. [Effective C++ --016]成对使用New和Delete时要采用相同形式

    这一节比较简单,可以总结为以下: std::string *stringPtr1 = new std::string; std::]; .. delete stringPtr1; // delete ...

  4. 条款16:成对使用new和delete时要使用相同的形式

    请牢记: 如果在new表达式中使用[],必须在相应的delete表达式中也使用[]. new[]  对应  delete[] 如歌在new表达式中不适用[],一定不要在相应的delete表达式中使用[ ...

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

    std::string* stringPtr1=new std::string; srd::string* stringPtr2=new std::string[100];   对应地 delete也 ...

  6. Effective C++ -----条款16:成对使用new和delete时要采取相同形式

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

  7. EC笔记:第三部分:16成对使用new和delete

    我们都知道,申请的资源,使用完毕后要释放.但是这个释放动作,一定要注意. 举个例子,很多人动态分配的资源,在使用之后,往往直接调用了delete,而不管申请资源的时候用的是new还是new[]. 如下 ...

  8. 【16】成对使用new和delete时要采取相同形式

    简而言之,new时不带[],delete时也不带[]:new时带[],delete时也要带[].如果不匹配,要么造成多销毁对象,导致未定义行为:要么导致少销毁对象,导致内存泄漏.

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

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

随机推荐

  1. SharePoint 如何使自己的网页自动跳转

    SharePoint 如何使自己的网页自动跳转         SharePoint自动制作自己的网页跳的很easy,只有在页面上要添加一个Web部分--内容编辑器,对应的js代码就可以.       ...

  2. java安全编程

    java安全程序实际上是一个点稍微防御性编程意味着内,竟java作为编程语言,较C,c++,本身被认为是比较安全的,随着C,C++这样的偏底层的编程语言比,java少了显示的指针调用.少了程序上的内存 ...

  3. 采纳ajax提交POST样本数据

    问题叙述性说明 我们会form该input和checkbox提交给异步数据phpserver.处理后的回. 提交之后显示的位置: 难点分析 採用from表单的onsubmit属性阻止表单的提交 < ...

  4. 前端学习笔记(zepto或jquery)——对li标签的相关操作(三)

    对li标签的相关操作——八种方式遍历li标签并获取其值 $("ul>li").forEach(function(item,index){ alert(index+" ...

  5. IntelliJ IDEA 开发scala

    1.下载安装IntelliJ IDEA,并安装scala插件 我下载的是linux的13版本,linux版本是绿色版本,有一个启动的脚本,运行就可以了,也可以在linux建立快捷方式.windows的 ...

  6. CSharp设计模式读书笔记(18):中介者模式(学习难度:★★★☆☆,使用频率:★★☆☆☆)

    中介者模式(Mediator Pattern):用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互,中介者模式又称为 ...

  7. 使用Bootstrap

    开始使用Bootstrap 作为一名Web开发者而言,如果不借助任何前端框架,从零开始使用HTML和CSS来构建友好的页面是非常困难的.特别是对于Windows Form的开发者而言,更是难上加难. ...

  8. [Unity3D]Unity3D游戏开发之Unity与Android交互调用研究

    各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei.在前一篇文章中,我们研究了Android平台上Unity3D的手势操作并在之前的基础 ...

  9. ssh ipv6

    从这里学来的.http://blog.mattandanne.org/2012/01/sftpscp-and-ipv6-link-local-addresses.html当采用ipv6的地址去连接另外 ...

  10. Hadoop与HBase中遇到的问题(续)java.io.IOException: Non-increasing Bloom keys异常

    在使用Bulkload向HBase导入数据中, 自己编写Map与使用KeyValueSortReducer生成HFile时, 出现了以下的异常: java.io.IOException: Non-in ...