在析构函数中修改类成员对象会导致未定义的行为吗?
Does modifying class member objects in the destructor result in undefined behavior?
例如:
struct B { int b_; };
struct D : B
{
~D()
{ // D object's lifetime ends here
d_ = 0; // (1) undefined behavior?
b_ = 0; // (2) undefined behavior also?
}
int d_;
};
c++标准定义了对于D
类型的对象,当析构函数~D()
调用开始时,其生命周期结束。
我们是否可以将其解释为在析构函数中修改对象(如(1))会导致未定义的行为?
如果是这样,如果我们修改D
的基类子对象,是否同样适用,如(2)?
这两个访问都是未定义的,它们都是完全可以的。
虽然析构函数的生命周期在开始时结束是正确的,但仍然可以以有限的方式使用该对象,定义为:N4140§3.8 [basic。生活[6]
同样,在对象的生命周期之前对象已启动,但在该对象将占用的存储空间之后或在对象的生命周期结束后在对象占用的存储空间被重用或释放之前,任何指向原始对象的全局值都可以使用,但只能在有限的方法。关于正在构建或销毁的对象,请参见(class.cdtor) .
和类。cdtor]:
N4140§12.7 [class。cdtor]/1
对于具有非平凡析构函数的对象,引用any析构函数之后的对象的非静态成员或基类完成执行导致未定义行为。
上面清楚地说明,只有在析构函数完成之后,才能触摸该对象的成员。
您所展示的示例都不是未定义行为。它们是完美定义的。
类实例在析构函数返回之前一直存在。对象的成员不是在析构函数被调用之前销毁,而是在它返回之后销毁。因此,在析构函数中修改类的成员是完全合法的。而且在子类被完全销毁之前,父类不会被销毁,所以修改父类的成员也是完全可以的。
一般来说,对象通过以下过程被销毁:
- 析构函数被调用。
- 类成员按其初始构造的相反顺序被销毁。 步骤1和2在对象的超类中重复。
(为了简单起见,我忽略了虚拟继承,这里不相关)。
相关文章:
- 添加自定义析构函数时,Move 构造函数在派生类中消失
- 在从仅移动类型派生的类中定义析构函数在使用 std::vector emplace_back或push_back创建时会
- 为什么在定义析构函数时隐式删除移动构造函数
- 仅在删除包含对象的向量时调用自定义»析构函数«
- 这个递归类需要一个自定义析构函数?
- C++ - 定义自定义析构函数时程序崩溃
- 对象超出范围后未调用析构函数
- 定义析构函数可以防止成员函数内联
- 在scoped_ptr发生异常的情况下未调用析构函数
- 使用自定义析构函数时出现"Undefined reference"错误
- 未调用析构函数
- C++ 在迭代器类中定义析构函数
- `不可复制`与自定义析构函数
- 堆栈上的对象被覆盖时未调用析构函数
- 是否可以使用 std::shared_ptr 创建共享对象池,并在没有自定义析构函数的情况下创建weak_ptr
- 我们什么时候必须在派生类 c++ 中定义析构函数
- 未调用析构函数
- C++unique_ptr未调用析构函数
- 未调用析构函数,程序异常退出时出现问题
- 抛出异常时未调用析构函数