我遇到了我的第一个编译器,它改变了传递给:: delete的左值,但没有将左值归零。这是以下情况:
Foo * p = new Foo();
Foo * q = p;
assert(p != 0);
assert(p == q);
::delete p;
assert(p != q);
assert(p != 0);
请注意,删除操作后p不为零,并且已从其旧值更改。一位同事告诉我,他在使用一些将p改为0xFFFFFFFF的大型机C ++编译器以及将p改为0的其他编译器的经验并不罕见。
在C ++标准中,它是否允许编译器执行此操作?
通过StackOverflow搜索,我发现了这个问题:Why doesn’t delete set the pointer to NULL?有一个引用Bjarne Stroustrup's response的答案,其中包含声明:
C ++明确允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎。
我已阅读并重新阅读final committee draft C++0x standard的第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);
在这种情况下,行为已有详细记录。当delete获得一个空指针时,它假设什么也不做,所以p保持不变。
答案 0 :(得分: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)。否则,未指定是否将调用释放功能。 [注意:无论对象的析构函数或数组的某个元素是否引发异常,都会调用释放函数。 - 结束说明]