gpt4 book ai didi

c++ - 我应该删除内部创建线程的类的复制构造函数和赋值运算符吗?

转载 作者:行者123 更新时间:2023-12-02 04:43:04 26 4
gpt4 key购买 nike

当一个类拥有线程和互斥对象时,是否存在任何潜在的危险情况,其中复制/赋值是危险的,这意味着应该删除复制构造函数和赋值?

考虑这个示例代码:

class A : B
{
std::thread t;
std::mutex m;

public:
A() : B() {}
virtual ~A()
{
if (t.joinable())
t.join();
}

// Should I delete cctor and assignment operator?

virtual void Method()
{
t = std::thread([this]
{
std::lock_guard<std::mutex> lck(m);
... // processing
});
}

// Other methods that lock on mutex m
};

如果我理解正确的话,在 Method() 中创建的线程在 A 之外将不可见,这意味着使用默认 cctor 进行复制应该不会有问题,因为整个状态都会被复制。我的推理正确吗?

最佳答案

任何(扩展)状态包含指向自身的指针的类都必须具有已删除的拷贝/移动,或者必须编码该状态。

t = std::thread([this] 

上面的行在类的扩展状态下存储了一个指向 this 的指针。

因此,默认复制和移动是不合适的。删除是一种选择;小心翼翼地、可能代价高昂地编码另一个。

此外,线程和互斥体都是仅移动类型。因此拷贝将被隐式删除。

但是,您的移动分配/构造将由编译器编写并且错误。因此删除它们或修复它们。

<小时/>

没有类值类型的语言(如 Java/C#)有一个习惯用法,即拥有一个具有状态的类和一个处理该状态的线程。对于像 C++ 这样以值(value)为中心的语言来说,这是一个糟糕的计划。将您的状态存储在外部(例如,共享或唯一的 ptr),与您的线程共享(作为共享 ptr 或观察 ptr),突然间默认移动就有意义了。

如果不这样做,你的对象就会变得无柄——无法安全地移动——这会削弱许多伟大的 C++ 习惯用法,或者强制外部智能指针包装。

关于c++ - 我应该删除内部创建线程的类的复制构造函数和赋值运算符吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48137834/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com