删除数组时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++ 上对其进行测试。

在删除“简单”类型的数组时,deletedelete [] 的工作方式似乎相同。

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++下deletedelete []是一样的? 第二个测试用例,为什么g++不像第一个测试用例那样处理?

【问题讨论】:

您如何确认第一种情况没有内存泄漏,两种情况都没有内存错误? 请仔细阅读这个问题 - ***.com/q/1913343/57428 详细解释了所有原因。 就内存释放而言,它的处理方式可能与第一种情况相同。在这两种情况下,总分配大小通常以相同的方式存储,因此内存被正确释放。但是,delete[] 旨在为每个分配的对象调用析构函数,而 delete 只会在第一个对象上调用它,即 a[0]。这就是发生内存泄漏的原因。 A 对象内部的 int 数组没有被释放,因为没有调用析构函数,但 A 对象的初始分配被正确释放。无论哪种方式,这都是不可移植的未定义行为。 【参考方案1】:

这一切都依赖于底层的内存管理器。简单来说,C++ 要求你用delete[] 删除数组,用delete 删除非数组。标准中没有解释你的行为。

然而,可能发生的是delete p; 只是释放从p 开始的内存块(无论它是否是一个数组)。另一方面,delete[] 额外遍历数组的每个元素并调用析构函数。由于像char 这样的普通数据类型没有析构函数,因此没有任何效果,所以deletedelete[] 最终会做同样的事情。

就像我说的,这都是特定于实现的。不能保证delete 可以在任何类型的数组上工作。它恰好适用于您的情况。在 C++ 中,我们称之为未定义的行为——它可能会起作用,也可能不会,它可能会做一些完全随机且出乎意料的事情。您最好避免依赖未定义的行为。

【讨论】:

【参考方案2】:
char * a = new char[1024];
delete a; // the incorrect way. also NO memory leak.

没有。它不保证No memory leak。它实际上调用了未定义的行为。

【讨论】:

【参考方案3】:

deletedelete[] 在 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[]一样吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

js删除数组中的元素delete和splice的区别

delete 和vue.delete 删除数组的区别

delete和Vue.delete删除数组的区别

javascaipt中数组元素删除方法delete和splice

JQ 数组删除(splice和delete)

C 中的 free 和 C++ 中的 delete 之间的区别?