我有一个类,它有一个 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:
只保护指向线程可能访问的资源的指针,并将该指针指向它。
在您的情况下,这意味着:
move
running_
:struct inner { std::atomic<bool> running; }; unique_ptr<inner> data_ = new inner;
传递指向的数据:
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/