在 C++ 的析构函数中允许做什么?
What is allowed to do in destructors in C++?
我正在尝试了解在析构函数中允许做什么。
standard 说:“对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基 class 会导致未定义的行为".
cppreference 这样描述析构序列:“对于用户定义的或隐式定义的析构函数,在执行析构函数体后,编译器会为 [= 的所有非静态非变体成员调用析构函数23=]".
这是否意味着,在下面的代码中,从其成员的析构函数中调用方法是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_;
};
此外,标准中的短语“析构函数完成后”究竟是什么意思?在析构函数的主体完成之后?或者在所有成员和基地 classes 被摧毁之后?
我认为最后一个问题的答案是理解什么是允许的,什么不是的关键。
Bar
的析构函数还没有结束,所以引用Bar
的一个成员,确实可以在其析构函数中调用Bar
的成员函数。
虽然调用超对象的成员函数可能有点不稳定,因为成员函数可能访问子对象,而一些子对象可能在调用成员函数时已经被销毁,在这种情况下访问被破坏的对象会导致未定义的行为。在您的示例中不是这种情况。
Or by "referring" standard means something particular?
我觉得是形成一个指针或者指向子对象的引用。正如规则下方示例中所做的那样。
Also, what does the phrase "after the destructor finishes" from the standard mean exactly? After the body of a destructor finishes? Or after all members and base classes destroyed?
后者。
先执行主体,然后析构函数调用子对象析构函数,然后析构函数完成。
我正在尝试了解在析构函数中允许做什么。
standard 说:“对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基 class 会导致未定义的行为".
cppreference 这样描述析构序列:“对于用户定义的或隐式定义的析构函数,在执行析构函数体后,编译器会为 [= 的所有非静态非变体成员调用析构函数23=]".
这是否意味着,在下面的代码中,从其成员的析构函数中调用方法是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_;
};
此外,标准中的短语“析构函数完成后”究竟是什么意思?在析构函数的主体完成之后?或者在所有成员和基地 classes 被摧毁之后?
我认为最后一个问题的答案是理解什么是允许的,什么不是的关键。
Bar
的析构函数还没有结束,所以引用Bar
的一个成员,确实可以在其析构函数中调用Bar
的成员函数。
虽然调用超对象的成员函数可能有点不稳定,因为成员函数可能访问子对象,而一些子对象可能在调用成员函数时已经被销毁,在这种情况下访问被破坏的对象会导致未定义的行为。在您的示例中不是这种情况。
Or by "referring" standard means something particular?
我觉得是形成一个指针或者指向子对象的引用。正如规则下方示例中所做的那样。
Also, what does the phrase "after the destructor finishes" from the standard mean exactly? After the body of a destructor finishes? Or after all members and base classes destroyed?
后者。
先执行主体,然后析构函数调用子对象析构函数,然后析构函数完成。