访问其用户定义的析构函数已启动但未完成的对象真的是 UB 吗?
Is it really UB to access an object whose user-defined destructor has started, but not finished?
这个问题是由于 a discussion on Reddit 引起的,一位用户引用标准的对象生命周期规则告诉我:
I'm pretty certain that it is technically UB to access an object, while it is being destructed.
我靠这个,比如用类管理后台线程;我让他们的析构函数通知线程退出并等待它退出,并且该线程可以访问该对象。我需要重构我的代码吗?
不对,定义明确
如果在对象的析构函数执行时完全无法访问该对象,则该析构函数本身将无法对其自己的对象执行任何操作。
在你的析构函数执行期间:
- 基地还没有被摧毁
- “当前”对象本身还没有被破坏(也没有它的成员)
- 一些资源可能已经被释放,如果你已经在你的析构函数中这样做了
- 派生子对象已被破坏
- 虚函数调用将安全地引用“当前”对象,而不是这些现已失效的派生子对象
dynamic_cast
和 typeid
会做同样的事情
- 不过,您不能使用
Derived*
执行任何这些操作!通过 Base*
或 Current*
即可
[class.cdtor]
涵盖了大部分规则。
尽管对象的生命周期 确实 在技术上以析构函数“调用”的开始结束,此时您处于一种炼狱中 [class.cdtor]
结束上面列出的规则:
[basic.life/7]
: [..] after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. [..]
它可能是一种容易出错且令人困惑的模式,但它本身并不是不正确的。对于您的特定用例,我什至称其为合理的常规。
这个问题是由于 a discussion on Reddit 引起的,一位用户引用标准的对象生命周期规则告诉我:
I'm pretty certain that it is technically UB to access an object, while it is being destructed.
我靠这个,比如用类管理后台线程;我让他们的析构函数通知线程退出并等待它退出,并且该线程可以访问该对象。我需要重构我的代码吗?
不对,定义明确
如果在对象的析构函数执行时完全无法访问该对象,则该析构函数本身将无法对其自己的对象执行任何操作。
在你的析构函数执行期间:
- 基地还没有被摧毁
- “当前”对象本身还没有被破坏(也没有它的成员)
- 一些资源可能已经被释放,如果你已经在你的析构函数中这样做了
- 派生子对象已被破坏
- 虚函数调用将安全地引用“当前”对象,而不是这些现已失效的派生子对象
dynamic_cast
和typeid
会做同样的事情- 不过,您不能使用
Derived*
执行任何这些操作!通过Base*
或Current*
即可
[class.cdtor]
涵盖了大部分规则。
尽管对象的生命周期 确实 在技术上以析构函数“调用”的开始结束,此时您处于一种炼狱中 [class.cdtor]
结束上面列出的规则:
[basic.life/7]
: [..] after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. [..]
它可能是一种容易出错且令人困惑的模式,但它本身并不是不正确的。对于您的特定用例,我什至称其为合理的常规。