删除数组时delete和delete[]一样吗? [复制]
Posted
技术标签:
【中文标题】删除数组时delete和delete[]一样吗? [复制]【英文标题】:Delete and delete [] are the same when deleting arrays? [duplicate] 【发布时间】:2011-10-20 16:10:39 【问题描述】:可能的重复:How could pairing new[] with delete possibly lead to memory leak only?( POD )freeing memory : is delete[] equal to delete?
使用 gcc 版本 4.1.2 20080704 (Red Hat 4.1.2-48)。尚未在 Visual C++ 上对其进行测试。
在删除“简单”类型的数组时,delete
和 delete []
的工作方式似乎相同。
char * a = new char[1024];
delete [] a; // the correct way. no memory leak.
char * a = new char[1024];
delete a; // the incorrect way. also NO memory leak.
但是,当删除“复杂”类型的数组时,delete
会导致内存泄漏。
class A
public:
int m1;
int* m2; // a pointer!
A()
m2 = new int[1024];
~A()
delete [] m2; // destructor won't be called when using delete
;
A* a = new A[1024];
delete [] a; // the correct way. no memory leak.
A* a = new A[1024];
delete a; // the incorrect way. MEMORY LEAK!!!
我的问题是:
-
第一个测试用例,为什么g++下
delete
和delete []
是一样的?
第二个测试用例,为什么g++不像第一个测试用例那样处理?
【问题讨论】:
您如何确认第一种情况没有内存泄漏,两种情况都没有内存错误? 请仔细阅读这个问题 - ***.com/q/1913343/57428 详细解释了所有原因。 就内存释放而言,它的处理方式可能与第一种情况相同。在这两种情况下,总分配大小通常以相同的方式存储,因此内存被正确释放。但是,delete[] 旨在为每个分配的对象调用析构函数,而 delete 只会在第一个对象上调用它,即 a[0]。这就是发生内存泄漏的原因。 A 对象内部的 int 数组没有被释放,因为没有调用析构函数,但 A 对象的初始分配被正确释放。无论哪种方式,这都是不可移植的未定义行为。 【参考方案1】:这一切都依赖于底层的内存管理器。简单来说,C++ 要求你用delete[]
删除数组,用delete
删除非数组。标准中没有解释你的行为。
然而,可能发生的是delete p;
只是释放从p
开始的内存块(无论它是否是一个数组)。另一方面,delete[]
额外遍历数组的每个元素并调用析构函数。由于像char
这样的普通数据类型没有析构函数,因此没有任何效果,所以delete
和delete[]
最终会做同样的事情。
就像我说的,这都是特定于实现的。不能保证delete
可以在任何类型的数组上工作。它恰好适用于您的情况。在 C++ 中,我们称之为未定义的行为——它可能会起作用,也可能不会,它可能会做一些完全随机且出乎意料的事情。您最好避免依赖未定义的行为。
【讨论】:
【参考方案2】:char * a = new char[1024];
delete a; // the incorrect way. also NO memory leak.
没有。它不保证No memory leak
。它实际上调用了未定义的行为。
【讨论】:
【参考方案3】:delete
和 delete[]
在 g++ 中看似等价纯属运气。在分配有new[]
的内存上调用delete
,反之亦然,是未定义的行为。只是不要这样做。
【讨论】:
【参考方案4】:因为那是未定义的行为。不保证会坏,但也不保证能正常工作。
【讨论】:
【参考方案5】:delete表达式在释放内存之前调用要删除的对象的析构函数。释放内存可能在任何一种情况下都有效(但它仍然是 UB),但如果你在需要 delete[]
的地方使用 delete
,那么你就不会调用所有的析构函数。由于您的复杂对象本身会分配内存,而这些内存又会在自己的析构函数中释放,因此当您使用错误的表达式时,您将无法进行所有这些删除。
【讨论】:
【参考方案6】:它们在技术上并不相同,它们只是在非复杂类型上被优化为相同的含义。复杂类型需要向量化的delete
,以便可以为delete
数组中的每个对象调用析构函数(就像构造函数的向量化new
)。
你所做的只是释放内存,就像它的指针数组一样。
【讨论】:
【参考方案7】:这里发生的是,当您调用 delete 时,对象占用的空间被删除。在 chars 的情况下,这就是您需要做的所有事情(尽管仍然建议使用 delete[],因为这只是 g++。在 c++ 标准中未定义对数组调用 delete 的实际行为。)。
在第二个示例中,数组占用的空间被释放,包括指针 m2。但是,m2 所指向的内容并没有被删除。当您调用 delete[] 时,会调用数组中每个对象的析构函数,然后释放 m2 指向的内容。
【讨论】:
以上是关于删除数组时delete和delete[]一样吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章