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

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

时间:2015-08-08 22:37:46      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

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

来看一个例子:
std::string* stringArray = new std::string[100];
...
delete stringArray;

  问题:stringArray所含的100个string对象中的99个可能并没有被适当地删除,因为它们的析构函数很可能没有被调用。


我们来了解一下,使用new时发生了什么,一共有两个动作:
  1. 内存被分配出来
  2. 针对此内存会有一个或更多个构造函数被调用
使用delete,也有两个动作:
  1. 针对此内存会有一个或更多个析构函数被调用
  2. 内存被释放
这个问题的关键:
delete的最大问题在于,即将被删除的内存之内究竟有多少个对象?这个问题的答案决定了有多少个析构函数必须被调用。
简单地说就是:
即将被删除的那个指针,所指的是单一对象,还是对象数组。因为单一对象的内存布局和对象数组的内存布局是不一样的。更明确的说,数组所用的内存通常还包括“数组大小”的记录,以便delete知道需要调用多少次析构函数。单一对象的内存则没有这笔记录。
你可以把两种不同的内存布局想象如下的形式,其中n是数组的大小:
技术分享

当你对着一个指针使用delete,唯一能够让delete知道内存中是否存在一个“数组大小记录”的方法就是:有你来告诉它。如果你使用delete时加上中括号,delete便认定指针指向一个数组,否则它便认定指针指向单一对象。
像下面的代码:
std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];
...
delete stringPtr1;
delete[] stringPtr2;

  如果对stringPtr1使用delete[]形式,delete会读取若干内存并将它解释为“数组大小”,然后开始多次调用析构函数。这是很危险的,同时编译器是不会帮你检查的。

如果对stringPtr2使用delete形式,这会导致较少的析构函数被调用,这种错误对于内置类型int也是不可以的,虽然这种类型没有析构函数。


 

所以游戏规则很简单:

如果你调用new时,使用new[] 的形式,那么对应调用delete时也使用[],
如果你调用delete时,没有使用new[] 的形式,那么对应调用delete时也不应该使用[] 形式。

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

// 这时候AddresLines是一个数组,所以new时,应该是[]形式
std:string* pal = new AddresLines;        // 相当于:new string[4];
//那么,必须匹配数组形式的delete
delete pal;         // error,行为未定义
delete[] pal;      // pass 

  所以,最好尽量不要对数组形式使用typedef动作。


 

 最后在看360的一道在线笔试题目:
假定指针变量p定义为“int *p=new int(100);”,要释放p所指向的动态内存,应使用语句delete p还是delete[] p。

  这个问题很简单,注意int后面是小括号,所以:

1.new int[] 是创建一个int型数组,数组大小是在[]中指定,例如:
int * p = new int[10]; //p执行一个长度为10的int数组。

2. new int()是创建一个int型数,并且用()括号中的数据进行初始化,例如:
int *p = new int(10); // p指向一个值为10的int数。

  所以正确的形式是delete p;

 

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

标签:

原文地址:http://www.cnblogs.com/stemon/p/4714000.html

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