你为什么要写这样的东西? (故意不在数组上使用delete [])

时间:2009-04-24 20:16:23

标签: c++ coding-style

我偶尔会遇到这种代码 - 我怀疑创建者是/害怕表删除会迭代表和“性能表现”(imho不会以任何方式完成)...是可以从不使用表删除这里得到/考虑/想象的真正好处吗?

myClass** table = new myClass* [size];
... //some code that does not reallocate or change the value of the table pointer ;)
delete table; // no [] intentionally

8 个答案:

答案 0 :(得分:19)

如果你这样做,你将得到C ++标准所谓的未定义行为 - 任何事情都可能发生。

答案 1 :(得分:8)

这是内存泄漏。 new []必须与delete []匹配。此外,由于table是指向指针数组的第一个元素的指针,因此任何数组成员(如果它是一个数组本身)都需要使用delete []取消分配。

答案 2 :(得分:8)

不仅没有任何好处,代码只是完全错误 - 充其量,它会泄漏内存,最糟糕的是,它可能会导致程序崩溃或打开难以找到的安全漏洞。您必须始终将newdeletenew[]delete[]匹配。总是

答案 3 :(得分:5)

因为新的[]需要与delete []配对,这绝对是错误的。如果不这样做,您将得到未定义的行为。

它可能(部分)工作,因为大多数实现使用new来实现new []。这种实现的唯一区别是它只会调用1个析构函数(对于第一个元素而不是所有析构函数。但是要避免它,因为它不合法c ++

答案 4 :(得分:4)

真的没有理由这样写,也没有理由不这样做。

对于具有普通析构函数的类型(在您的情况下类似于原始指针),确实无需知道数组中元素的实际数量,因此编译器可能决定映射 new [] 删除[] new delete 以减少开销。如果它以这种方式决定你不能在没有采取额外步骤的情况下停止它,那么这个编译器优化将在没有你通知的情况下进行并且是免费的。

与此同时,有人使用您的代码可能希望重载全局运算符 new delete (以及 new [] 删除[] 。如果发生这种情况,您会遇到大麻烦,因为这可能是您真正需要 delete delete [] 之间的区别。

此外,这种依赖于编译器的优化是不可移植的。

所以当你没有利用删除来取代 delete [] 这样的情况时会出现这种情况,但是很有可能依赖于未定义的行为。

答案 5 :(得分:2)

理论上你应该调用delete []。

编辑:以下内容仅适用于Microsoft Visual C ++ (我应该这样说)。

实际上,在Microsoft Visual C ++中,当数组中的对象没有析构函数时,使用哪个删除无关紧要。既然你有一个指针数组,并且指针不能有析构函数,你应该没问题。

然而,正如其他人所指出的那样,在没有[]的情况下混合new []和delete是不正确的C ++。虽然在这种情况下它可能在Visual C ++中工作,但代码不可移植,并且可能在其他编译器中失败。

但回到Visual C ++的特定情况,即使你调用delete [],编译器也会意识到当它是一个原始类型数组(如int,char)时,它不需要遍历调用析构函数的数组。或指针。在这种情况下调用删除实际上是有效的,不会破坏任何东西。做正确的事并调用delete []并不会慢,但它也不会更快。

实际上,在MSVC ++中,当p是指向简单类型的指针或没有析构函数的指针时,delete [] p会立即调用常规运算符delete(void * p)。

那些不相信我的人,将这段代码单步执行到前两次调用删除[]的CRT代码中。

#include "stdafx.h"
#include <malloc.h>
#include <iostream>
using namespace std;

class NoDestructor
{
    int m_i;
};

class WithDestructor
{
public:
    ~WithDestructor()
    {
        cout << "deleted one WithDestructor at " << (void *) this<< endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    int **p = new int *[20];
    delete [] p;

    p = (int**) malloc(80);
    free(p);

    NoDestructor *pa = new NoDestructor[20];
    delete [] pa;

    WithDestructor *pb = new WithDestructor[20];
    delete [] pb;

    return 0;
}

答案 6 :(得分:1)

该语句将保留数组中所有指针所指向的所有myClass对象在内存中。它还将指针数组留在内存中。没有办法可以提供帮助,因为它只释放了32位内存,操作系统仍然认为你有(大小)myClasses和指向每个使用的指针。这只是一个程序员没有正确清理的例子。

答案 7 :(得分:1)

查看[16.11]部分“如何分配/取消分配一系列内容?”在C ++ FAQ Lite中,

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.11

他们解释说,在创建数组时必须删除数组。

数组元素指向的myClass的实例也应该在创建它们的地方删除。