加入成员线程访问父析构函数中其父类的其他成员会导致未定义的行为吗?

Vit*_*meo 4 c++ multithreading undefined-behavior language-lawyer c++11

我的一位同事声称,一旦对象的析构函数调用开始,由线程(该对象本身的成员)完成对对象成员的所有访问都是UB.

这意味着std::thread::join如果线程正在访问任何对象的其他成员,则在对象的析构函数期间调用是UB.

我在"对象生命周期"下简要介绍了最新的标准草案,但找不到能给我一个确定答案的东西.

以下代码(在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;
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 6

这不是未定义的行为.如果我们看一下[class.dtor]/8

在执行析构函数的主体并销毁在主体内分配的任何自动对象之后,类X的析构函数调用X的直接非变量非静态数据成员的析构函数,X的直接基类的析构函数,如果X是最派生类的类型(12.6.2),它的析构函数调用X的虚拟基类的析构函数.

表明在析构函数体运行后,类的非静态成员被销毁.这意味着所有成员在析构函数中都处于活动状态,并且操作x和调用join行为就像在普通成员函数中一样.唯一的区别是在析构函数的主体运行之后,成员本身将被销毁.