c++ - 在父类的析构函数中加入成员线程访问其父类的其他成员是否会导致未定义的行为?

标签 c++ multithreading c++11 language-lawyer undefined-behavior

我的一位同事声称,一旦对象的析构函数调用开始,线程(对象本身的成员) 对对象成员的所有访问都是 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/

相关文章:

c++ - 使用指针复制构造函数

c++ - std::sort 是否检查 vector 是否已经排序?

c++ - 访问链表中的数据成员

c++ - 当我运行这段代码时它是 "stopped working"。我想从 API 调用这个简单的函数

c++ - C++ 数组是通过引用传递还是通过指针传递?

java - 将数据从多个线程发送到单个线程

c++ - 在主程序退出期间销毁等待 std::condition_variable 的线程的正确方法

c# - 我无法停止线程

c++ - 如何将枚举返回值转换为 C++ 异常?

c++ - 强制复制省略?海湾合作委员会 5.4.1