我的一位同事声称,一旦对象的析构函数调用开始,线程(对象本身的成员) 对对象成员的所有访问都是 UB。
这意味着如果线程正在访问对象的任何其他成员,则在对象的析构函数期间调用 std::thread::join
是 UB。
我在“对象生命周期” 下简要查看了最新的标准草案,但找不到可以给我结论性答案的内容。
是否执行以下代码 (on wandbox)引入未定义的行为?阐明此交互的标准部分是什么?
struct A
{
atomic<bool> x{true};
thread t;
// Capturing 'this' is part of the issue.
// The idea is that accessing 'this->x' becomes invalid as soon as '~A()' is entered.
// vvvv
A() : t([this]
{
while(x)
{
this_thread::sleep_for(chrono::milliseconds(100));
}
})
{
}
~A()
{
x = false;
t.join();
}
};
int main()
{
A a;
}
最佳答案
这不是未定义的行为。如果我们看一下 [class.dtor]/8 我们有
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes.
这说明类的非静态成员在析构函数体运行后被销毁。这意味着所有成员在析构函数中都处于事件状态,并且操作 x
和调用 join
的行为就像它们在普通成员函数中一样。唯一的区别是在运行析构函数的主体之后,成员本身将被销毁。
关于c++ - 在父类的析构函数中加入成员线程访问其父类的其他成员是否会导致未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40403417/