我有一个具有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?
}
[this]
。running_
之后step 1
之前的lambda中访问哪个对象step 2
?答案 0 :(得分:1)
虽然std::thread
肯定是可移动的,但这样做并不能神奇地修改引用它的任何指针或其包含的对象(如果有的话)。
因此,即使在移动C
之后,由包含的std::thread
管理的线程仍将引用它之前引用的对象。
因此,如果您想安全地移动/交换C
,请使用pimpl-idiom:
只安全指向线程可能访问的资源的指针,并将指针指向它
在您的情况下,这意味着:
移动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) {
...
}
});
(也可选择移动线程未访问的数据。)
此外,即使您没有提问,您的running
也必须是std::atomic<bool>
,以便检查有效。