我在试着理解在析构函数中允许做什么。
标准说:“对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基类会导致未定义的行为”。
优先选择以这种方式描述销毁序列:“对于用户定义或隐式定义的析构函数,在执行析构函数的主体后,编译器调用类的所有非静态非变体成员的析构函数”。
这是否意味着,在下面的代码中,从其成员的析构函数调用方法是UB?或者说“参照”标准指的是一些特殊的东西?
struct Foo {
Foo(Callback cb) : cb_(cb) {}
~Foo() {
// body of Bar destructor finished at this moment;
// cb_() calls Bar::call_me()
cb_();
}
Callback cb_;
};
struct Bar {
// pass callback with captured this
Bar() : foo_([this]() { call_me(); }) {
}
void call_me() {
}
// foo is a member, its destructor will be called after Bar destructor
Foo foo_;
};
另外,标准中的“析构函数完成后”这个短语到底意味着什么?在破坏者的身体完成之后?或者在所有的成员和基类被摧毁之后?
我认为最后一个问题的答案是理解什么是允许的和什么是不允许的关键。
发布于 2021-05-18 03:12:32
Bar
的析构函数尚未完成,因此引用Bar
的一个成员,实际上在其析构函数中调用Bar
的成员函数是可以的。
但是,调用超级对象的成员函数可能有点不稳定,因为成员函数可以访问子对象,并且在调用成员函数时某些子对象可能已经被销毁,在这种情况下,访问被破坏的对象将导致未定义的行为。在您的示例中,情况并非如此。
或者说“参照”标准指的是一些特殊的东西?
我认为这意味着形成一个指针或一个对子对象的引用。正如在下面的示例中所做的那样。
另外,标准中的“析构函数完成后”这个短语到底意味着什么?在破坏者的身体完成之后?或者在所有的成员和基类被摧毁之后?
后者。
主体首先执行,然后析构函数调用子对象析构函数,然后析构函数完成。
https://stackoverflow.com/questions/67584695
复制相似问题