在NULL指针上调用delete - C++ 03 vs C++ 11

R S*_*ahu 21 c++ language-lawyer delete-operator c++11 c++03

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

5.3.5删除

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

在C++ 11 Draft Standard(N3337)中,我看到:

5.3.5删除

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

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

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

  2. 如果标准草案的措辞在实际标准中保持不变,那么在2003年和2011年之间将强有力的陈述改为几乎没有任何理由的理由是什么?

Sha*_*our 24

看起来我们可以在缺陷报告348中找到这种变化的理由,其中说:

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

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

标准没有指定术语"无效".从该上下文中不清楚,被调用的释放函数是否需要不起作用,或者delete-expression不应该调用释放函数.

此外,在第4段标准中说明了默认的释放功能:

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

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

如果"无效"是解除分配函数的要求,则应在3.7.4.2 [basic.stc.dynamic.deallocation]或18.6.1.1 [new.delete.single]和18.6.1.2中说明[ new.delete.array],应该明确说明.

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


Pup*_*ppy 10

最新的C++ 14草案(N3797)在本节中具有大致相同的措辞.但是这种行为同样强烈地指明,而不是完全相同的段落.

如果delete-expression的操作数的值不是空指针值,则delete-expression将调用该对象的析构函数(如果有)或要删除的数组的元素.在数组的情况下,元素将按地址递减的顺序销毁(即,与构造函数完成的顺序相反;见12.6.2).

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

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

  • 很难想象这种变化可能解决的任何真正的问题.看起来像政治对我来说.我可以改变pl3z的措辞吗? (4认同)
  • 重新"我真的不在乎",你关心的东西*你试图反对我的观察,首先是一个明确的断言,然后是权威论证谬论,现在假装冷漠.这是你不关心的技术内容吗?完全非技术性质的是你关心的(足够做到这一点)吗? (3认同)