删除数组时删除和删除[]是否相同?

时间:2011-08-05 08:28:11

标签: c++ arrays memory-management g++

  

可能重复:
  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!!!

我的问题是:

  1. 在第一个测试用例中,为什么deletedelete []在g ++下是相同的?
  2. 在第二个测试用例中,为什么g ++不像第一个测试用例那样处理它?<​​/ li>

7 个答案:

答案 0 :(得分:9)

这完全取决于底层内存管理器。简而言之,C ++要求您删除带有delete[]的数组,并删除带有delete的非数组。标准中没有解释您的行为。

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

就像我说的,这是所有特定的实现。无法保证delete可以在任何类型的数组上运行。它恰好适用于您的情况。在C ++中,我们称之为未定义的行为 - 它可能起作用,它可能不起作用,它可能会做一些完全随机和意外的事情。你最好避免依赖未定义的行为。

答案 1 :(得分:6)

char * a = new char[1024];
delete a; // the incorrect way. also NO memory leak.

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

答案 2 :(得分:3)

deletedelete[]看起来在g ++中是等价的,纯粹是运气。在分配有delete的内存上调用new[],反之亦然,是未定义的行为。只是不要这样做。

答案 3 :(得分:1)

因为那是未定义的行为。它不能保证会中断,但也不保证能够正常工作。

答案 4 :(得分:1)

delete 表达式在释放内存之前调用要删除的对象的析构函数。释放内存可能适用于任何一种情况(但它仍然是UB),但是如果你在需要delete的地方使用delete[],那么你就不会调用所有的析构函数。由于您的复杂对象本身会分配内存,而内存又在其自己的析构函数中释放,因此当您使用错误的表达式时,您无法进行所有这些删除。

答案 5 :(得分:0)

它们在技术上并不相同,它们只是在非复杂类型上被优化到相同的含义。复杂类型需要向量化delete,以便可以为数组delete中的每个对象调用析构函数(就像构造函数的向量化new一样)。

你做的只是自由的内存就像它的指针数组一样。

答案 6 :(得分:0)

这里发生的是当您调用delete时,将删除对象占用的空间。在chars的情况下,这就是你需要做的所有事情(尽管仍然建议使用delete [],因为这只是g ++。在c ++标准中,在数组上调用delete的实际行为是未定义的。)。

在第二个示例中,释放了数组占用的空间,包括指针m2。但是,m2指向的内容也不会被删除。当你调用delete []时,会调用数组中每个对象的析构函数,然后释放m2指向的内容。