【问题标题】:Calling delete on NULL pointers - C++03 vs C++11在 NULL 指针上调用 delete - C++03 与 C++11
【发布时间】:2014-10-09 09:00:45
【问题描述】:

在 C++03 标准中,我看到了:

5.3.5 删除

2 如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节的其余部分使用转换后的操作数代替原始操作数。 在任一备选方案中,如果 delete 的操作数的值为空指针,则该操作无效。 在第一个备选方案(删除对象)中, delete 的操作数应是指向非数组对象的指针或指向表示此类对象的基类(第 10 条)的子对象(1.8)的指针。如果不是,则行为未定义。在第二种选择(delete array)中,delete 的操作数的值应该是从前一个数组 new-expression 产生的指针值。72)如果不是,则行为未定义。

在 C++11 标准草案 (N3337) 中,我看到:

5.3.5 删除

2 如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节的其余部分使用转换后的操作数代替原始操作数。在第一种选择(删除对象)中,delete 的操作数的值可能是空指针值,指向由 a 创建的非数组对象的指针以前的 new-expression,或指向表示此类对象的基类的子对象 (1.8) 的指针(第 10 条)。如果不是,则行为未定义。在第二种选择(delete array)中,delete 的操作数的值可以是空指针值或从前一个数组new-expression 产生的指针值。如果不是,则行为未定义。

我已经强调了两个标准中的规范之间的差异。我觉得奇怪的是,2003 年的标准更强调必须如何处理 NULL 指针,而 2011 年的标准没有说明实现必须做什么。

  1. C++11 标准的措辞在标准草案和实际标准之间是否发生了变化?如果有,怎么做?

  2. 如果标准草案的措辞在实际标准中保持不变,那么在 2003 年至 2011 年间将非常强烈的声明更改为几乎没有的理由是什么?

【问题讨论】:

    标签: c++ c++11 language-lawyer c++03 delete-operator


    【解决方案1】:

    看起来我们可以在defect report 348 中找到这种变化的理由,其中说:

    具体来说,标准在 5.3.5 [expr.delete] 第 2 段中说:

    ...如果delete的操作数的值为空指针,则操作无效。

    标准没有指定术语“无效”。从不清楚 此上下文,是否需要调用的释放函数 没有效果,或者 delete-expression 不应调用释放 功能。

    此外,在第 4 段标准中提到了默认解除分配功能:

    如果删除表达式调用实现释放 函数(3.7.4.2 [basic.stc.dynamic.deallocation]),如果操作数 删除表达式不是空指针常量,...

    为什么对默认释放函数和delete-expr的交互如此具体?

    如果“没有效果”是释放功能的要求,那么 应在 3.7.4.2 [basic.stc.dynamic.deallocation] 或在 18.6.1.1 [new.delete.single] 和 18.6.1.2 [new.delete.array],应该明确说明。

    部分解决方案是您注意到的措辞变化,尽管围绕该措辞的语言已经发生了很大变化,但摆脱无效语言的逻辑仍然存在,它不是一个定义明确的术语,因此应替换为明确指定的语言。

    【讨论】:

    • 缺陷报告很好。其建议“则应在 3.7.4.2 中说明”是合理的。解决方案是拙劣的,因为它没有这样做:释放函数仍然可以使用空参数调用,这使得整个事情,C++11 保证没有这样的调用从删除表达式,没有意义,没有实用价值。
    【解决方案2】:

    最新的 C++14 草案 (N3797) 在本节中有大致相同的措辞。但这种行为同样被明确规定,只是不在同一个段落中。

    如果删除表达式的操作数的值不为空 指针值,删除表达式将调用析构函数(如果 any) 用于被删除的对象或数组的元素。在里面 数组的情况下,元素将按顺序销毁 递减地址(即按完成的相反顺序 他们的构造函数;看 12.6.2)。

    如果删除表达式的操作数的值不为空 指针值,则: — 如果分配调用 new-expression 对于要删除的对象没有省略( 5.3.4 ),删除表达式应调用释放函数( 3.7.4.2)。从 new-expression 的分配调用返回的值应作为第一个参数传递给 释放函数。 — 否则,删除表达式不会 调用释放函数 ( 3.7.4.2)。

    这些段落显然与 C++03 一样强大。委员会不可能破坏 delete 空指针的程序的行为,因为这些程序很普遍,而且修复的成本会太大。它会使 C++11 无法实现。

    【讨论】:

    • 很难想象这种变化可以解决任何实际问题。在我看来像政治。 pl3z,我可以修改一下措辞吗?
    • 另一个答案中的 DR 清楚地显示了更改解决了什么问题。
    • 我看不到如何实现“无效果”的更精细细节,这是一个问题。编写一个自定义的释放函数并依赖于一个 C++11 保证它不会被 0 调用,这是自找麻烦。
    • 补充说,第 3.7.4.2/4 节“如果在标准库中提供给释放函数的参数是一个不是空指针值 (4.10) 的指针,则释放函数应”意味着释放函数可以用空指针调用。保证没有来自 delete-expression 的此类调用没有实际意义。
    • 关于“我真的不在乎”,您对 某事 的关心已经足够了,以至于您试图用一个简单的断言来反驳我的观察,然后是一个权威论证谬误,现在装作漠不关心。那是你不关心的技术问题吗?您关心的(足以做到这一点)完全是非技术性的吗?
    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2014-06-26
    • 2014-10-01
    相关资源
    最近更新 更多