C++数组删除操作符语法

7

在我使用下面这行代码后

Foo* array = new Foo[N];

我通常会使用以下方式来释放它

delete[] array;

然而,有时候我会看到以下这种写法:

delete[N] array;

虽然这种写法好像编译并且工作正常(至少在msvc2005中),但我想知道:

什么是正确的做法?

为什么另一种方式也可以编译通过呢?

7个回答

13
你可以查看这个MSDN链接:delete[N] operator。该值将被忽略。 编辑 我在VC9上尝试了这个示例代码:
int test()
{
    std::cout<<"Test!!\n";
    return 10;
}

int main()
{
    int* p = new int[10];
    delete[test()] p;
    return 0;
};

输出为:Test!!

因此,表达式被计算但返回值被忽略了。我很惊讶,至少我无法想到这是为什么需要的情况。


这是否意味着您可以删除[2N]数组,并且可以通过编译? - Vivek Sharma
2
我的猜测是,这种语法在 C++ 的一个预标准方言中是有效的,因此“评估并忽略”的行为将需要对依赖于表达式副作用的古老代码进行假设的处理。我更惊讶的是,任何现代编译器都会默认启用对这种语法的支持。 - Mike Seymour

10

delete [N] array 是无效的。在C++标准中没有定义这个语法:第5.3.5节定义了删除表达式,它只有 delete expr 或者 delete [] expr 两种形式,没有其他形式。在gcc(4.1.2版本)中无法编译。至于为什么在Visual C++中可以编译: 请问微软。


哪个C++标准?你有一个可以找到它的链接/参考资料吗? - Kissaki
1
@Kissaki:我指的是C++03,它在网上没有合法版本。然而,在C++11中,措辞非常相似,其草案可在http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf上获得。 - Mike Seymour

5

delete[] array; is the correct form.


5
无论第二种情况是否正确,我建议使用第一种方法,因为它更少出错。
Visual Studio编译了很多不应该编译的东西。

4
Visual Studio编译了很多不该编译的东西。阿门。 - sbi

4
正确的方法是使用delete[] array;。我甚至不知道delete[N] array;会编译通过(我怀疑它应该不会)。

1
它在VC9上编译,但出现了“warning C4208:nonstandard extension used:delete [exp] - exp evaluated but ignored”警告。虽然我不知道这是什么意思。 - Naveen
1
这意味着代码(1)不是有效的C++代码,而且(2)表达式N被计算,但被忽略了。这个描述与实际情况无关,但它描述了如果你写了delete[N++] array;会发生什么——N首先增加,然后被忽略了。 - MSalters
实际上,它首先被忽略,然后再递增 :) - raven

4

第一点:几乎从来没有一个好的理由要使用数组形式的new或delete -- 而应该改用std::vector(或其他容器)。

第二点:回到C++的黑暗年代,你必须指定删除的数组大小,如果你使用了x = new T[N],匹配的delete语句则是delete [N] x。显式指定大小的要求早已被移除很久了,但一些编译器(特别是那些关心与古老代码向后兼容性的编译器)仍然允许这样做。

除非你确实需要保持与古老编译器(大约20年前的编译器)的兼容性,否则你不应该使用它。再说,除非你需要保持与一个不支持任何标准容器的老编译器的兼容性,否则你根本不应该使用new或delete的数组形式。请停止使用!


感谢您的历史课。那么,如果我必须将一个动态数组(例如浮点数)传递给第三方库,使用标准容器的正确方法是什么? - raven
使用向量。当需要传递地址/长度时,使用&vec[0]和vec.size()。 - Jerry Coffin
在1994年标准的草案中,语法已经是“delete[]”。同年,《设计与演化》(第218页)评论说,这种语法“...被证明过于容易出错,因此跟踪元素数量的负担被放在了实现上。” - Richard Corden

-2

如果它能工作,那就是一个非标准扩展。

delete [] array;   

是正确的形式。

delete array; 

有时候也可以工作,但这取决于实现(因此是错误的)。


1
第二个形式(不带括号)对于非数组指针的行为已经明确定义。但是对于数组的行为则没有。无论如何,我猜这就是为什么有人投了你反对票的原因。 - Raphaël Saint-Pierre
1
“delete array”在任何意义上都不“起作用”,除非你的意思是它不会使程序崩溃。它不会回收最初分配的所有内存,如果它没有崩溃,它只会运行数组中第一个对象的析构函数。(如果你使用了“new Foo[0]”,这也是一个错误。) - Bill
1
@Bill:我希望我能够对评论进行踩。你的说法有时可能是正确的,但有时可能不是。请看这里:https://dev59.com/JHI_5IYBdhLWcg3wDOdC 和我的评论在这里:https://dev59.com/JHI_5IYBdhLWcg3wDOdC - sbi
1
@Bill:delete array;(不带括号)在某些实现中确实会删除所有元素(这就是依赖于实现的含义),而且由于问题示例涉及int类型,因此没有需要调用的析构函数。 - Nicholaz
@sbi - 我认为你和我对“工作”的实际定义不同,但我理解你的观点。@Nicholaz - 好的,我没意识到有些实现是这样的。 - Bill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接