为什么我不应该在"删除"之后尝试使用"this"值?

sha*_*oth 27 c++ undefined-behavior

C++的这一段中,delete this讨论了构造的使用.列出了4个限制.

限制1到3看起来很合理.但是为什么限制4在那里我"必须不检查它,将它与另一个指针进行比较,将它与NULL进行比较,打印它,投射它,用它做任何事情"?

我的意思this是又一个指针.为什么我不能把reinterpret_castint或者叫它printf()输出它的值?

And*_*ett 37

调用delete之后'this'的值是未定义的,并且您对它执行的任何操作的行为也是未定义的.虽然我希望大多数编译器做一些合理的事情,但是没有(在规范中)阻止编译器决定它在这种特定情况下的行为将发出代码来格式化你的硬盘.调用未定义的行为(几乎)始终是一个错误,即使您的特定编译器按照您希望的方式运行.

您可以通过在调用delete之前获取指针的副本(作为整数)来解决此问题.

  • 此外,编译器今天的行为方式可能与下一个版本不同.未定义的确意味着"无法保证,永远". (4认同)
  • 虽然你可以在删除之前取指针的整数值 - 这是一个很好的经验法则,如果你绕过语言的机制进入"未定义的行为"领域 - 你只是在寻找麻烦,而且更好应考虑代码的基本设计. (3认同)

Kei*_*thB 29

删除指针(此指针或任何其他指针)后无法对指针执行任何操作的原因是硬件可能(以及一些较旧的计算机)陷阱尝试将无效的内存地址加载到寄存器中.尽管它可能适用于所有现代硬件,但标准规定,对无效指针(未初始化或删除)唯一可以做的就是分配给它(NULL或来自另一个有效指针).

  • 我会接受这个答案,因为它解释了为什么地狱可以解脱,而不仅仅是引用标准. (2认同)
  • @MarcvanLeeuwen:对于像 80286 这样的平台上的编译器来说,有可能(实际上并非不合理)将大于 32K 的对象表示为段的链接列表,每个段都有 32K 或更少的数据并包含链接该对象的第一个、下一个、上一个段,以及其在对象中的偏移量的指示。每个指针将标识一个段和其中的偏移量;比较两个指针需要使用存储在每个指针段底部的数据来查找对象的开头。 (2认同)

Ste*_*sop 28

啊哈!

3.7.3.2/4:"...释放函数应解除分配指针引用的存储空间,使所有指向解除分配存储的任何部分的指针无效.使用无效指针值的效果(包括将其传递给解除分配)功能)未定义".

请注意,这表示"使用值",而不是"取消引用指针".

该段并不具体this,它适用于任何已被删除的内容.

  • 同意.`p = NULL`很好,但`p = p - p;`不是 (3认同)
  • `p = p - p;`永远不会有效:) (3认同)
  • @naveen,不.p = NULL仍然有效.我们正在将指针更改为新位置,而不是使用删除指针的值.否则,所有指针变量只能使用一次. (2认同)
  • `pp`是"零整数"而不是"空指针常量为零".前者不会转换为空指针而后者将转换为空指针. (2认同)