Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我应该删除内部创建线程的类的复制构造函数和赋值运算符吗?_C++_Multithreading_Thread Safety_Copy Constructor - Fatal编程技术网

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

C++ 我应该删除内部创建线程的类的复制构造函数和赋值运算符吗?,c++,multithreading,thread-safety,copy-constructor,C++,Multithreading,Thread Safety,Copy Constructor,当一个类拥有线程和互斥对象时,是否存在任何潜在的危险情况,其中复制/赋值是危险的,这意味着复制构造函数和赋值应该被删除 考虑以下示例代码: class A : B { std::thread t; std::mutex m; public: A() : B() {} virtual ~A() { if (t.joinable()) t.join(); } // Should I delete

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

考虑以下示例代码:

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
};
A类:B类
{
标准:螺纹t;
std::互斥m;
公众:
A():B(){}
虚拟~A()
{
if(t.joinable())
t、 join();
}
//我应该删除cctor和赋值运算符吗?
虚空法()
{
t=std::thread([this]
{
标准:锁紧装置lck(m);
…//处理
});
}
//锁定互斥锁m的其他方法
};

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

复制构造函数和赋值都需要删除或定义。如果你想删除它们,不要做任何事情:C++会隐式删除它们。 您的类有
std::mutex
作为成员。将删除其复制构造函数和赋值运算符。这使得C++也删除了类的赋值构造函数和赋值运算符,因为为它们生成默认行为需要调用删除的成员。 注意:删除不是您唯一的选择:如果您发现制作
A
的副本或使其可分配很有用,您可以选择定义复制构造函数和分配运算符,创建新线程和新互斥体,并复制对象的相关部分以支持您认为有用的语义。即使C++默认不为您做,您也可以手动选择。

< P>任何扩展(包括扩展)状态的指针都必须有删除的拷贝/移动,或者必须是MaSURE状态。
t = std::thread([this] 
上行将在类的扩展状态中存储指向此的指针

因此,默认的复制和移动是不合适的。删除是一种选择;小心地并且可能花费昂贵地编组另一个

此外,线程和互斥体都是只移动的类型。因此,副本将被隐式删除

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


没有类值类型的语言(如Java/C#)有一个习惯用法,即有一个带状态的类和一个在状态上工作的线程。在C++这样的以价值为中心的语言中,这是一个糟糕的计划。在外部存储您的状态(比如,一个共享的或唯一的ptr),与您的线程共享它(作为共享的ptr或作为观察的ptr),然后突然默认的移动就有了意义


不这样做,你的对象变得无柄-不能安全移动——这削弱了很多C++的成语,或者强制外部智能指针包装。然后

=delete
ing复制操作是明智的做法。它们将被隐式删除,因为您有
std::thread
std::mutex
作为成员。
thread
mutex
已经删除了复制,因此无论如何都无法复制您的类。但直言不讳可能是件好事,尤其是当你不确定自己的时候。:-)谢谢你@RichardCriten和BoPersson,事实就是这样,很抱歉我错过了。如果你把它移到一个答案,我会接受它。@RichardCriten线程删除它的复制构造函数。不过,这并不重要,因为互斥将同时删除这两个对象。