为什么编译器要求使用 `delete [] p` 而不是 `delete p[]`?

16

在 C++ 中,如果你想动态分配一个数组,你可以这样做:

int *p;
p = new int[i];  // i is some number

然而,要删除数组,您需要使用 delete[] 而不是 delete

delete[] p;

为什么不是delete p[]?那样岂不更符合最初创建的方式吗?如果有任何原因,为什么语言被设计成这样?


8
为什么会被踩/关闭问题? 我该如何改进问题? - Michael0x2a
5
@Deflect:那是我的观点。通常,“为什么选择这种语言结构?”这类问题并不具有建设性,因为没有客观、合理的答案。然而,在这种情况下,存在一些不错的理由,所以我可能判断过早了(我很快撤销了我的负评)。 - KillianDS
1
@KillianDS:好的,那很有道理。谢谢你的回复![并让我放心,我不是完全错了 :)] - Michael0x2a
@KillianDS:那么,为什么不直接回答“没有严重的原因,其他语言也这样做,只是C++走了自己的路”呢? - sharptooth
我不知道这有多有用,但这是我用英语阅读代码的方式:p是一个整数指针;p是一个长度为i的新整数数组;删除数组p。 - Jamie Taylor
2个回答

29

可能的一个原因是使这些情况更加明显区分。

int ** p;
delete[] p
delete p[1];
如果是delete p[],那么一个字符的错误就会产生相当严重的后果。

13
特别是在早期的C++中,你必须指定[]中元素的数量。 - James Kanze
4
听起来对我来说就是答案了。delete p[4]会有歧义。 - GManNickG
1
delete []p[1]; 也是有效的,编译器必须知道程序员的意图! - Ajay

2
因为数组在作为参数传递给函数(或运算符)时会衰减为指针。因此,删除p[]等效于简单地删除p。
[编辑] 我们可以将delete视为特殊的模板运算符。该运算符应该能够区分p和p[],以选择正确的“专业化”(非数组或数组删除)。然而,由于模板参数推导规则使得这种选择不可能(由于数组衰减,我们无法区分推导参数时的p[]和p)。
因此,我们不能对两种情况使用名称为delete的运算符,并需要引入另一个名为delete[]的运算符来处理数组情况(后缀[]可以视为运算符名称的一部分)。
[编辑2] 注意。根据当前标准,delete p[]根本不是有效的语法。上述推理仅显示了如果尝试使用现有的C++概念解释delete p[]可能出现的问题。

不,它们并不等价。在一个地方使用另一个会产生未定义的行为。 - sharptooth
@sharptooth: 把数组传递给模板化函数而不是指针是UB?我认为可以将其视为模板化运算符,而这个运算符无法选择正确的特化版本,因为它在推导参数时无法区分 p[] 和 p。因此,我们需要引入一个专门用于数组的特殊 operator delete[] 而不是使用相同的操作符名称。 - user396672
@sharptooth:当然,但这与我的回答无关。我只是说delete p和delete p[]是等效的语句(也许,如果p是由new int [i]创建的数组,则两者都会暴露UB)。 - user396672

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