为什么在数组的括号之间使用值不可能删除?

时间:2016-10-02 09:37:09

标签: c++

我理解在现代C ++编译器中,分配有new[]的数组的长度是秘密存储的(通常在数组后面),这样当调用delete[]时,编译器知道数组长度,但为什么我们可以不完全放弃,而是可以选择使用delete[n]释放那段记忆吗?

鉴于C ++支持您不会为不使用的内容付费的理想,并且始终知道阵列的长度通常是一个好主意,我不会&#39 ;了解为什么删除此功能。

1 个答案:

答案 0 :(得分:0)

逻辑上,删除此类功能的最常见原因是要么不需要,要么允许它增加错误程序行为的可能性。

然而,这个逻辑解释掩盖了很多细节,我将在这里讨论。

要使delete []表达式在没有未定义的行为的情况下工作,它需要能够访问在相应的new[]表达式中分配的实际长度。如果它不这样做,它就不能为动态分配的数组的每个元素调用析构函数(假设元素是带析构函数的类类型)。

让我们首先假设new[]的工作方式将分配的长度存储在a(我将在这里使用你的单词)“secret”(即特定于实现)方式中。这意味着delete []表达式不需要提供长度 - 实现可以访问正确的值,无论如何,并使用它。如果delete []表达式要提供长度,则实现可以忽略它(因为它无论如何都可以访问正确的值)或检查它。在实践中检查它没什么意义 - 如果提供的值不正确,实现可以报告它(例如写一条消息给std::cerr,调用abort())或忽略它(即使用正确的值)。无论哪种方式,检查delete[]表达式中提供的长度几乎没有价值。

或者,我们假设实现不以“秘密”方式存储分配的长度。然后有两种可能性 - 提供的长度是正确的还是不正确的。如果提供的长度正确,则delete []表达式按预期工作(数组元素的析构函数调用的正确数量,向主机系统释放正确的内存量等)。如果提供的长度不正确,则结果是未定义的行为(实现无法检测到问题,更不用说纠正它并使用正确的长度)。

现在,该标准应该做什么?三种可能性是要求delete []表达式提供长度,允许表达式提供长度(即使其成为可选),或者禁止提供长度。

如果需要delete []表达式来提供长度,如果delete[]表达式提供的长度不正确,则无法指定除未定义行为之外的任何内容。毕竟,一些实现会将正确的长度存储在“秘密”位置(因此他们可以忽略提供的长度),而其他实现只是无法检查值是否正确(即,如果{{{{{ 1}}表达式提供了错误的长度)。开发人员将依赖于实施问题的质量来获得可靠的行为 - 从某些实现而非其他实现。

如果delete []表达式被允许(可选)提供长度,那么实现将需要在“秘密”位置松开正确的长度 - 以确保{{1表达式没有提供长度。实际上,大多数实现会忽略所提供的长度,并且不需要delete []表达式来提供它。然而,开发人员和语言律师是他们的仆从,关于是否应该在delete []表达中提供长度,是否需要正确的长度以及结论将是 - 它没有',将会有很多争论。无所谓。这样的辩论对于学生来说可能是令人愉快的,但对于初学者来说,这会引起混淆。

最后一种可能性是禁止提供长度的delete []表达式。这具有要求实现将长度存储在“秘密”位置的效果。然后,delete []表达式的工作方式将访问长度,并按预期工作。

所以上述三种可能性相当于不必要地允许未定义的行为,导致开发人员在做什么或不做什么之间产生非生产性争论,或者delete []表达式在给定有效指针(其中有效指针)的情况下始终正常工作表示从delete []表达式获得的,未删除两次等等。)

最后一个选项 - 禁止在delete[]表达式中提供长度 - 是最合乎逻辑的。这恰好是标准规定的......

唯一的权衡是,有些人会查看历史记录(较旧的规格DID需要在new []表达式中提供长度)并要求解释...这将消耗带宽或智力要回答的问题。正如在这里开心一样。但是,世界永远不会完美,所以我们都生活在那里。