访问用户定义的析构函数已启动但未完成的对象真的是UB吗?

这个问题是由于Reddit上的讨论引起的,一位用户告诉我,引用了标准关于对象生命周期的规则:

我很确定在技术上访问一个对象是 UB,而它正在被破坏。

例如,我依赖于管理后台线程的类;我让他们的析构函数通知线程退出并等待它退出,并且该线程可以访问该对象。我需要重构我的代码吗?

回答

不,它的定义很好。

如果 UB 在其析构函数执行时访问该对象,则该析构函数本身将无法对其自己的对象执行任何操作。


在执行析构函数期间:

  • 基地尚未被摧毁
  • “当前”对象本身还没有被破坏(也没有它的成员)
  • 一些资源可能已经被释放,如果你已经在你的析构函数中这样做了
  • 派生的子对象已被破坏
    • 虚函数调用将安全地引用“当前”对象,而不是这些现已失效的派生子对象
    • dynamic_cast并且typeid会做同样的事情
    • 但是,您不能使用 a 执行任何这些操作Derived*!通过一个Base*Current*很好

这些规则中的大多数都包含在[class.cdtor].


尽管从技术上讲,对象的生命周期确实以析构函数“调用”的开始结束,但此时您处于一种炼狱中,其中[class.cdtor]接管了上面列出的规则:

[basic.life/7]: [..]在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,任何引用原始对象的泛左值都可以使用,但只能以有限的方式使用。对于正在构建或销毁的对象,请参阅 [class.cdtor]。[..]

这可能是一种容易出错且令人困惑的模式,但它本质上并不是不正确的。对于您的特定用例,我什至将其称为合理的常规。


以上是访问用户定义的析构函数已启动但未完成的对象真的是UB吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>