c++ - 安全 move 在访问其他成员的成员线程中运行 lambda 的对象

标签 c++ c++11 lambda move swap

我有一个类,它有一个 std::thread 成员变量,它运行一个依赖于其他成员变量的 lambda 函数。

举个例子:

struct C {
    C() {
        thread_ = std::thread([this]() {
            running_ = true;
            while (running_) {
                ...
            }
        });
    }
    C(C&& rv) {
        swap(rv);
    }
    void swap(C& rhs) {
        std::swap(thread_, rhs.thread_); // step 1
        std::swap(running_, rhs.running_); // step 2
    }
    std::thread thread_;
    bool running_;
};

int main() {
    C c;
    C c2 = move(c); // Is c safely moved to c2?
}
  • move 此类物体的安全方法是什么?
  • 捕获[this] move 操作后要指向的对象。
  • 第 1 步之后但第 2 步之前,在 lambda 的 while 循环中访问了哪个对象的 running_

最佳答案

虽然 std::thread肯定是可 move 的,这样做不会神奇地修改任何引用它的指针,或者它的包含对象,如果有的话。

因此,即使你 move 了一个 C ,由包含的 std::thread 管理的线程仍将引用它之前引用的对象。

所以,如果你想安全地 move/交换一个 C , 使用 pimpl-idiom:
只保护指向线程可能访问的资源的指针,并将该指针指向它。
在您的情况下,这意味着:

  1. move running_ :

    struct inner {
        std::atomic<bool> running;
    };
    unique_ptr<inner> data_ = new inner;
    
  2. 传递指向的数据:

    auto data = &*data_;
    thread_ = std::thread([data]() {
        data->running = true;
        while (data->running) {
            ...
        }
    });
    

(可选地也 move 线程未访问的数据。)

此外,即使您没有询问,您的 running必须是 std::atomic<bool>所以检查有效。

关于c++ - 安全 move 在访问其他成员的成员线程中运行 lambda 的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28214142/

相关文章:

c# - protobuf-net 缺少可选字段的 has_ 函数?

c++ - 如何为性能设计对象

c++ - 在 basic_string 中查找 STL::Exception 的来源

c++ - 如何使用 C++11 的最小 gc 支持

c++ - namespace::variable 的多重定义,即使使用 ifndef

c++ - 在 C++ 中重载 setter/getter ?

c# - 使用辅助方法创建动态 lambda

c++ - DDS C++ - 数据分发服务

python - 使用 lambda 打印斐波那契数列并在 python 中映射或减少

list - 迭代一个 optional 整数列表 ifPresent