在C++标准中它说的是什么:: delete可以改变左值?

Ant*_*nts 8 c++ pointers lvalue delete-operator c++11

我遇到了第一个改变传递给:: delete的左值的编译器,但没有将左值归零.这是以下情况:

 Foo * p = new Foo();
 Foo * q = p;
 assert(p != 0);
 assert(p == q);
 ::delete p;
 assert(p != q);
 assert(p != 0);
Run Code Online (Sandbox Code Playgroud)

请注意,删除操作后p不为零,并且已从其旧值更改.一位同事告诉我,他在使用一些将p改为0xFFFFFFFF的大型机C++编译器以及将p改为0的其他编译器的经验并不罕见.

在C++标准中,它是否允许编译器执行此操作?

通过StackOverflow搜索,我发现了这个问题:为什么不删除将指针设置为NULL?有一个答案提到Bjarne Stroustrup的答复,其中包括声明:

C++显然允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎.

我已经阅读并重新阅读了最终委员会草案C++ 0x标准的第5.3.5和12.5节,但我没有看到"明确"部分.我只是在寻找标准的错误部分吗?或者这些部分中是否存在一系列逻辑,但我只是没有正确连接在一起.

我没有Annotated C++ Reference Manual的副本了.编译器是否可以在ARM中执行此操作?

[编辑:将部分参考从3.5.3更正为5.3.5.我还添加了一个有趣的悖论作为Henk断言删除后p未定义的对立点.

如果将p初始化为null,则存在一个有趣的悖论.

 Foo * p = 0;
 Foo * q = p;
 assert(p == 0);
 assert(p == q);
 ::delete p;
 assert(p == q);
 assert(p == 0);
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,行为已有详细记录.当delete获得一个空指针时,它假设什么也不做,所以p保持不变.

Dav*_*eas 8

它可能不那么明确.在5.3.5/7中,它表示delete表达式将调用deallocator函数.然后在3.7.3.2/4中,它说使用已经解除分配的指针是未定义的.由于在重新分配后不能使用指针的值,因此指针是保持值还是由实现改变了值没有区别.

5.3.5/7

delete-expression将调用释放函数(3.7.3.2).

3.7.3.2/4

如果给标准库中的释放函数赋予的参数是一个不是空指针值的指针(4.10),则释放函数将释放指针引用的存储,使所有指向引用任何部分的指针无效.解除分配存储.使用无效指针值(包括将其传递给释放函数)的效果未定义.

参考文献来自现行标准.在即将推出的标准5.3.5/7中已经改写:

C++ 0x FD 5.3.5/7

如果delete-expression的操作数的值不是空指针值,则delete-expression将调用释放函数(3.7.4.2).否则,未指定是否将调用释放功能.[注意:无论对象的析构函数或数组的某个元素是否引发异常,都会调用释放函数. - 结束说明]

  • @Henk:我完全同意编译器的意图,即支持"快速失败,早期失败"的理念.它暴露了代码中的一个错误,该代码已经运行了近10年.我们有一个双向链表实现,它自动更新节点析构函数中的下一个,前一个和第一个节点指针.列表的析构函数被编码为"while(m_firstNode)delete m_firstNode;" 节点析构函数正确更新m_firstNode,但编译器在析构函数调用后使用非零值覆盖m_firstNode.KABOOM!如果它是明确的,原始代码将是不同的. (2认同)