今天发现写的一段代码,new了数组后,使用的delete而不是delete[]释放,没有内存泄漏。结合以前一些对delete和new的一些模糊了解,查阅了相关资料,整理了本文。
目录:
1、new 操作
2、delete与delete[]
3、案例分析
4、参考文献
实验环境是Windows XP + VC6.0
1、new操作
这里将new和new[]等不严谨的统称为new操作
C++中提供了new操作符来进行C++类在堆上的创建。new相比较C的malloc而言,不仅分配了内存,而且对创建的C++类调用了其构造函数进行构造工作。在分配内存时,被分配的内存会有一些额外空间记录分配的大小。具体记录在哪里,找了下malloc()源代码没找着,希望知道的网友能够回复一下。先谢过了。
2、delete与delete[]
由于new操作记录内存大小,所以delete的时候,会根据需要删除的指针的地址找到额外空间,根据其大小删除所分配的内存。这么说来,delete与delete[]在释放内存,即free这一块是一样的。存在的区别在于delete[]需要将类的析构函数作用于每一个元素。delete只是将析构作用于第一个元素。析构完成后,再释放内存。
那为什么不将两个delete统一为delete[]呢,原因引用《深度探索C++对象模型》P259的描述,“寻找数组维度给delete运算符的效率带来极大的影响,所以才导致这样的妥协:只有在中括号出现时,编译器才寻找数组的维度,否则它便假设只有单独一个objects要被删除。”
在平时使用中,对于new[]产生的东西,最好是使用delete[]来释放,这样可以让每个元素都得以析构,否则的话,可能会产生一些问题。比如元素类的构造中产生了内存,在析构中需要去释放内存时,使用delete便会使得从第二个开始的元素没有被析构,导致内存泄漏。
3、案例分析
存在class CA,定义如下
class CA
{
public:
CA();
~CA();
private:
int m_iCount;
char* m_szContent;
};
1)某段代码如下:
CA* pVecA = new CA[10];
delete pVecA;
pVecA = NULL;
a)如果CA的析构函数不需要释放内存不会造成内存泄漏,只是析构函数没有作用于第2-10个元素。
b)如果CA的析构函数需要释放内存,则pVecA中2-10元素因为未执行析构,导致内存泄漏。
2)某段代码如下:
class CB: public CA
{
//内容省略
};
CA* pVecA = new CB[10];
delete[] pVecA;
pVecA = NULL;
其中,delete[]会根据CA的大小遍历pVecA,将CA的析构函数作用于元素上,会存在两个问题。
a)~CA()并不能满足~CB()的功能
b)CA的大小与CB不等,导致delete[]计算元素大小时错误,CA的析构作用于不正确的内存块上。
3)某段代码如下:
CA* pVecA = new CA[10];
pVecA++;
delete pVecA;
程序会异常,个人推断,是因为new[]分配的内存大小是一次分配的,其大小只记录在首元素前面的额外空间内。所以遍历一个元素之后,删除会异常。从而得到以下一个推论:
一次new N个元素所占用的内存比new N个元素所占用的内存小,少了N-1个额外空间。
4、参考文献:
《深度探索C++对象模型》