***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************
三、Resource Management
Rule 16:Use the same form in corresponding use of new and delete
规则 16:成对使用 new 和 delete 时要采用相同的形式
1.现象
先看下下面动作有什么错?
<span style="font-size:14px;">std::string* stringArray = new std::string[100]; ... delete stringArray;</span>
所有的东西看起来都不错( 使用了 new 创建,并且也用 delete 进行了释放 ),BUT ,还是能找出错误:程序行为不明确。也就是说,stringArray所含有的100个元素,可能有99个没有被适当的消除,因为它们的析构函数没有被调用。
2.一些基本
当我们使用 new 时,会发生两件事:
①. 内存被分配出来 ( 通过名为 operator new 的函数 )
②. 针对此内存会有一个(或更多) 构造函数被调用。
当我们使用 delete 时,也会发生两件事:
①. 针对此内存会有一个(或更多)析构函数被调用。
②. 然后 此内存 才会被释放( 通过 operator delete 的函数)
关于delete的最大的问题在于: 即将被删除的内存之内究竟存有多少对象,这个问题的答案也决定了 有多少个析构函数必须被调用起来。
让问题更简单一些:即将被删除的指针,指向单一对象 还是 对象数组?
单一对象: Object
对象数组: n Object Object Object ...
3.我来告诉它
当你对着一个指针使用 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,之前也提到过,100个对象,只有1个被释放,造成内存的浪费。
△ 其实,new 和 delete 的游戏规则 非常简单—— 如果调用 new 时,用了 [ ] ,你必须在对应调用delete时 使用 [ ] ; 如果 调用 new 时,没用[ ] ,你也不应该在用 delete时用 [ ]。
4.其他,还有啥?
这个规则,还要注意的就是 使用 typedef 的人。 它们要说清楚, 程序员用 new 创建该种 typedef类型对象时,该用哪种delete来删除。
由于 AddressLines是个数组,如果这样用new:typedef std::string AddressLines[4]; // 每个人的地址有四行,每行类型都是 string
std::string* pal = new AddressLines; // 它返回一个 string*对象
它相当于: new string[4]
所以,必须匹配的delete是:
总结: 这样很难以知道,我们应该用哪种delete形式,所以,为了避免这样的错误, 最好尽量不要 对数组形式 进行 typedef动作。 这也很容易去更改,因为C++标准程序库 含有 string、vector这样的 template。delete pal; // 这样就错了! delete [ ] pal; // 这样才对
5.请记住
★ 如果你在 new 表达式中使用[],必须在相应的delete表达式中也是用[]。如果你在 new 表达式中,不使用[],一定不要在相应的delete表达式中使用[]。
***************************************转载请注明出处:http://blog.csdn.net/lttree ********************************************