访问用户定义的析构函数已启动但未完成的对象真的是UB吗?
这个问题是由于Reddit上的讨论引起的,一位用户告诉我,引用了标准关于对象生命周期的规则:
我很确定在技术上访问一个对象是 UB,而它正在被破坏。
例如,我依赖于管理后台线程的类;我让他们的析构函数通知线程退出并等待它退出,并且该线程可以访问该对象。我需要重构我的代码吗?
回答
不,它的定义很好。
如果 UB 在其析构函数执行时访问该对象,则该析构函数本身将无法对其自己的对象执行任何操作。
在执行析构函数期间:
- 基地尚未被摧毁
- “当前”对象本身还没有被破坏(也没有它的成员)
- 一些资源可能已经被释放,如果你已经在你的析构函数中这样做了
- 派生的子对象已被破坏
- 虚函数调用将安全地引用“当前”对象,而不是这些现已失效的派生子对象
dynamic_cast并且typeid会做同样的事情- 但是,您不能使用 a 执行任何这些操作
Derived*!通过一个Base*或Current*很好
这些规则中的大多数都包含在[class.cdtor].
尽管从技术上讲,对象的生命周期确实以析构函数“调用”的开始结束,但此时您处于一种炼狱中,其中[class.cdtor]接管了上面列出的规则:
[basic.life/7]: [..]在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,任何引用原始对象的泛左值都可以使用,但只能以有限的方式使用。对于正在构建或销毁的对象,请参阅 [class.cdtor]。[..]
这可能是一种容易出错且令人困惑的模式,但它本质上并不是不正确的。对于您的特定用例,我什至将其称为合理的常规。