关闭

delete和delete[]的区别

标签: C++
78人阅读 评论(0) 收藏 举报
分类:

转载地址:http://blog.csdn.net/hazir/article/details/21413833
C++中,类型分为两种:内置类型和自定义的类类型。在释放内存时分为释放内置类型和自定义类型的数组。
1、对于单个对象,释放内置类型和类类型的方法一样,使用delete.对于类对象而言,delete做两件事:
(1)调用类的析构函数;
(2)释放对象的内存;
2、对于动态申请到的数组,调用delete[]进行释放

string *psa = new string[10];      
int *pia = new int[10];     
delete [] psa;
delete [] pia;     

上面在申请一个数组时都用到了 new [] 这个表达式来完成,第一个数组是 string 类型,分配了保存对象的内存空间之后,将调用 string 类型的默认构造函数依次初始化数组中每个元素;第二个是申请具有内置类型的数组,分配了存储 10 个 int 对象的内存空间,会进行默认初始化,但由于在函数内部,默认初始化为未定义。

都用到 delete [] 表达式,注意这地方的 [] 一般情况下不能漏掉!我们也可以想象这两个语句分别干了什么:第一个对 10 个 string 对象分别调用析构函数,然后再释放掉为对象分配的所有内存空间;第二个因为是内置类型不存在析构函数,直接释放为 10 个 int 型分配的所有内存空间。

这里对于第一种情况就有一个问题了:我们如何知道 psa 指向对象的数组的大小?怎么知道调用几次析构函数?
这个问题直接导致我们需要在 new [] 一个类对象数组时,需要保存数组的维度,C++ 的做法是在分配数组空间时多分配了 4 个字节的大小,专门保存数组的大小,在 delete [] 时就可以取出这个保存的数,就知道了需要调用析构函数多少次了。
在delete[]时,这里要注意的两点是:调用析构函数的次数是从数组对象指针前面的 4 个字节中取出;传入 operator delete[] 函数的参数不是数组对象的指针 pAa,而是 pAa 的值减 4。

为什么 new/delete 、new []/delete[] 要配对使用?

int *pia = new int[10];
delete []pia;

这肯定是没问题的,但如果把 delete []pia; 换成 delete pia; 的话,会出问题吗?
但如果不调用析构函数呢(如内置类型,这里的 int 数组)?我们在 new [] 时就没必要多分配那 4 个字节, delete [] 时直接释放为 int 数组分配的空间。如果这里使用 delete pia;那么将会调用 operator delete 函数,传入的参数是分配给数组的起始地址,所做的事情就是释放掉这块内存空间。所以不存在问题的。这里说的使用 new [] 用 delete 来释放对象的提前是:对象的类型是内置类型或者是无自定义的析构函数的类类型!

class A *pAa = new class A[3];
delete pAa;

那么 delete pAa; 做了两件事:

1、调用一次 pAa 指向的对象的析构函数;
2、调用 operator delete(pAa); 释放内存。

显然,这里只对数组的第一个类对象调用了析构函数,后面的两个对象均没调用析构函数,如果类对象中申请了大量的内存需要在析构函数中释放,而你却在销毁数组对象时少调用了析构函数,带来以下缺点:
1、这会造成内存泄漏
2、上面的问题你如果说没关系的话,那么第二点就是致命的了!直接释放 pAa 指向的内存空间,这个总是会造成严重的段错误,程序必然会奔溃!因为分配的空间的起始地址是 pAa 指向的地方减去 4 个字节的地方。你应该传入参数设为那个地址!只释放了4字节之后的第一个对象,相当于内存中就中断了部分,造成段错误

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:27059次
    • 积分:1162
    • 等级:
    • 排名:千里之外
    • 原创:87篇
    • 转载:29篇
    • 译文:0篇
    • 评论:1条
    最新评论