Effective C++学习笔记总链接
改善程序与设计的55个具体做法学习笔记-每日1条
条款16:成对使用new和delete时要采用相同形式
【技巧】
如果你在new的表达式中使用[],必须在相应的delete表达式中也使用[];你在new表达式中不使用[],一定不要在相应的delete表达式汇总使用[]。
以下程序有什么错误?
std::string* stringArray = new std::string[100];
...
delete stringArray;
完全错误:程序出现行为不明确(未有定义)。
stringArray 所含的100个string对象中的99个不太可能被适当删除,因为它们的析构函数很可能没被调用。
使用new时
- 内存被分配出来
- 针对此内存会有一个或更多构造函数被调用
使用delete时
- 针对此内存会有一个或者更多析构函数被调用
- 内存被释放
delete最大的问题在于:
即将被删除的内存之内究竟存在多少对象?
这个问题的答案决定了有多少析构函数必须被调用起来
更简单的表述是:
即将被删除的那个指针,所指的是单一对象或者对象数组
更明确的说:
数组所用的内存通常还包括“数组大小”的记录,以便delete知道需要调用多少次析构函数,单一对象的内存则没有这笔记录。
如何让delete知道内存中是否存在“数组大小”记录?
由你告诉它,如果你使用delete时加上中括号[],delete便认定指针指向一个数组,否则它便认定指针指向单一对象
std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];
...
delete stringPtr1; //删除一个对象
delete [] stringPtr2; //删除一个由对象组成的数组
错误使用delete会发生什么?
当stringPtr1使用“delete[]” ,结果未有定义。delete会读取若干内存并将它解释为“数组大小”,然后开始多次调用析构函数,浑然不知它所处理的那块内存不但不是个数组,也或许并未持有它正忙着销毁的那种类型的对象。
当stringPtr2没有使用“delete[]”,结果亦未有定义,可能导致太少的析构函数被调用。这对内置类型如int亦未有定义(甚至有害),即使这类类型并没有析构函数。
delete如何使用?
如果你调用new时使用[],你必须在对应调用delete时也使用[]。
如果你调用new时没有使用[],那么也不该在对应调用delete时使用[]。
不要对数组使用typedef
typedef std::string AddressLines[4];
std::string* pal = new AddressLines;
//注意:“new AddressLines”返回一个string*,就像“new string[4]”一样
delete pal; // 错误,行为未有定义!
delete[] pal; // 正确delete
为了避免诸如此类的错误,最好尽量不要对数组形式做typedef动作。