1.对应的 new 和 delete 要采用相同的形式 下面的语句有什么错?
string *stringarray = new string[100];
...
delete stringarray;
一切好象都井然有序——一个 new 对应着一个 delete——然而却隐藏着很大的错误:程序
的运行情况将是不可猜测的。至少,stringarray 指向的 100 个 string 对象中的 99 个不会被正
确地摧毁,因为他们的析构函数永远不会被调用。
用 new 的时候会发生两件事。首先,内存被分配(通过 operator new 函数,详见条款 7-10 和
条款 m8),然后,为被分配的内存调用一个或多个构造函数。用 delete 的时候,也有两件
事发生:首先,为将被释放的内存调用 一个或多个析构函数,然后,释放内存 (通过
operator delete 函数,详见条款 8 和 m8)。对于 delete 来说会有这样一个重要的问题:内存
中有多少个对象要被删除?答案决定了将有多少个析构函数会被调用。
这个问题简单来说就是:要被删除的指针指向的是单个对象呢,还是对象数组?这只有你
来告诉 delete。假如你在用 delete 时没用括号,delete 就会认为指向的是单个对象,否则,
它就会认为指向的是一个数组:
string *stringptr1 = new string;
string *stringptr2 = new string[100];
...
delete stringptr1;// 删除一个对象
delete [] stringptr2;// 删除对象数组
假 如你在 stringptr1 前加了 "[]" 会怎样呢?答 案是:那将是不可猜测的;假如 你没在
stringptr2 前没加上"[]"又会怎样呢?答案也是: 不可猜测。而且对于象 int 这样的固定类型
来说,结果也是不可猜测的,即使这样的类型没有析构函数。所以,解决这类问题的规则
很简单:假如你调用 new 时用了[],调用 delete 时也要用[]。假如调用 new 时没有用[],那
调用 delete 时也不要用[]。
在写一个包含指针数据成员,并且提供多个构造函数的类时,牢记这一规则尤其重要。因
为这样的话,你就必须在所有初始化指针成员的构造函数里采用相同的 new 的形式。否则,
析构函数里将采用什么形式的 delete 呢?关于这一话题的进一步阐述,参见条款 11。
这个规则对喜欢用 typedef 的人来说也很重要,因为写 typedef 的程序员必须告诉别人,用
new 创建了一个 typedef 定义的类型的对象后,该用什么形式的 delete 来删除。举例如下:
typedef string addresslines[4]; //一个人的地址,共 4 行,每行一个 string
//因为 addresslines 是个数组,使用 new:
string *pal = new addresslines; // 注重"new addresslines"返回 string*, 和
// "new string[4]"返回的一样
delete 时必须以数组形式与之对应:
评论0