问题聚焦:
    我们都知道,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. HR系统邮件审批功能总结

    时至今日,来兰亭工作的第三个小任务算是暂时告一段落了.这个小任务是耗费时间最长的,因此在这里总结整理一下. 首先这个功能的出发点是方法领导进行手下员工的审批,包括加班申请,休假申请,和漏打卡申请.由于 ...

  2. /proc/mtd 各参数的含义 -- linux内核

    经/proc虚拟文件系统读取MTD分区表:cat /proc/mtd mtd .name = raspi, .size = 0x00400000 (4M) .erasesize = 0x0001000 ...

  3. UI測试内容

    我们在实际工作其中,针对web应用程序,也就是常常所说的B/S系统,能够从例如以下方面来进行用户界面測试: 导航測试 导航描写叙述了用户在一个页面内操作的方式,在不同的用户接口控制之间,比如butto ...

  4. hdu2602 Bone Collector (01背包)

    本文来源于:http://blog.csdn.net/svitter 题意:典型到不能再典型的01背包.给了我一遍AC的快感. //================================== ...

  5. 提高你的Java代码质量吧:推荐在复杂字符串操作中使用正则表达式

    一.分析  字符串的操作,诸如追加.合并.替换.倒序.分隔等,都是在编码过程中经常用到的,而且Java也提供了append.replace.reverse.split等方法来完成这些操作,它们使用起来 ...

  6. hdu 质方数

    Problem Description   小明天生对数字比较敏感,3岁的时候就能背诵圆周率一百位. 现在,小明慢慢长大了,但依然很喜欢数字,最近,他迷上了质数和平方数,并且自己把质数的平方命名为“质 ...

  7. EF4.1: Add/Attach and Entity States(EF中的实体状态转换说明)

    实体的状态,连接以及 SaveChanges 方法 数据库上下文对象维护内存中的对象与数据库中数据行之间的同步.这些信息在调用 SaveChanges方法被调用的时候使用.例如,当使用 Add 方法传 ...

  8. 【翻译自mos文章】v$undostat视图没有依照每10分钟进行更新,v$undostat仅仅有1行(one rows)

    v$undostat视图没有依照每10分钟进行更新,v$undostat仅仅有1行(one rows) 參考原文: The V$UNDOSTAT view is not getting updated ...

  9. BCM策略路由交换芯片

    BCM几个交换芯片的寄存器和相关的路由 EGR_L3_NEXT_HOP.EGR_L3_INTF.ING_L3_NEXT_HOP BCM XGS系列SDK中和路由相关的几个命令 l3 l3table. ...

  10. [CLR via C#]5.3 值类型的装箱和拆箱

    原文:[CLR via C#]5.3 值类型的装箱和拆箱 在CLR中为了将一个值类型转换成一个引用类型,要使用一个名为装箱的机制. 下面总结了对值类型的一个实例进行装箱操作时内部发生的事: 1)在托管 ...