我有一个带有使用类成员的线程对象的类。
class MyClass
{
private:
atomic_int a;
thread t;
public:
MyClass()
: a(0),
t([this]() // <- grab 'this' pointer
{
while(true)
{
sleep_for(milliseconds(1000));
a++; // <- use 'a' field of the object (through 'this')
}
})
{
}
};
问题:如何实现移动分配/构造函数,以便线程对象引用新的MyClass对象?
天真的(不好的)实现:
class MyClass
{
public:
MyClass(MyClass&& other)
: a(other.a),
t(other.t) // <- Thread object is moved to the new MyClass object
// but it's still referencing the old 'this' pointer.
{
}
}
最佳答案
您无法移动atomic
对象。这是一个提示:虽然您可以编写自己的move构造函数以将旧对象的a
初始化为旧对象的unique_ptr
,但行为不会是原子的! (您还必须在线程之间进行同步,以发布新的原子对象的地址。)
所以不要移动它。这立即意味着原子对象一定不能是可移动类的(直接)成员。接下来的最简单的事情(除了将其设置在lambda之外,这可能是不希望的)是通过this
(已经具有所需的可移动性但不具有可复制性)来拥有它。然后,lambda可以捕获原始指针,以避免引用可能悬挂的terminate
(的子对象):
class MyClass
{
private:
unique_ptr<atomic_int> a;
thread t;
public:
MyClass()
: a(new atomic_int(0)),
t([a=a.get()]() // <- grab pointer to atomic
{
while(true)
{
sleep_for(milliseconds(1000));
++*a;
}
})
{
}
};
这样,默认的move构造函数/赋值是正确的。 (请注意,如果线程仍在运行,则分配调用
atomic_int
,这是有道理的,因为您只是重新分配了正在使用的ojit_code!)关于c++ - 在C++线程对象中重新绑定(bind)* this, move 构造函数, move 赋值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49588418/