C++ 如何将互斥体用作成员变量?没有'的复制构造函数;简易编码器&x27;被隐式删除

C++ 如何将互斥体用作成员变量?没有'的复制构造函数;简易编码器&x27;被隐式删除,c++,mutex,C++,Mutex,您好,我正在尝试创建一个多线程编码器,它需要一个互斥体,我希望该互斥体成为该类的成员。但是,我不断得到:simple\u encoder的复制构造函数被隐式删除,因为字段“m\u mutex”在编译时有一个无法访问的复制构造函数作为错误消息。经过一个小时的搜寻,我找不到我的错误 出于对某些事物的热爱,请帮助我,我的构造函数和成员如下所示: namespace master_thesis { class simple_encoder { public: simple_encoder(ui

您好,我正在尝试创建一个多线程编码器,它需要一个互斥体,我希望该互斥体成为该类的成员。但是,我不断得到:
simple\u encoder的复制构造函数被隐式删除,因为字段“m\u mutex”在编译时有一个无法访问的复制构造函数作为错误消息。经过一个小时的搜寻,我找不到我的错误

出于对某些事物的热爱,请帮助我,我的构造函数和成员如下所示:

namespace master_thesis
{
class simple_encoder
{
public:

    simple_encoder(uint32_t symbols, uint32_t symbol_size, fifi::api::field field,
                   std::vector<uint8_t> data) :
        m_symbols(symbols), m_symbol_size(symbol_size),
        m_completed(0), m_field(field), m_data(data)
    {

    }
...
private:

    uint32_t m_symbols;
    uint32_t m_symbol_size;
    uint32_t m_completed; 

    fifi::api::field m_field;

    std::mutex m_mutex;

    std::vector<uint8_t> m_data;
    std::vector<std::vector<uint8_t>> m_result;

    std::vector<std::shared_ptr<kodo_rlnc::full_vector_encoder>> m_encoders;
};
}
namespace硕士论文
{
类简单编码器
{
公众:
简单编码器(uint32符号、uint32符号大小、fifi::api::字段、,
std::矢量数据):
m_符号(符号),m_符号大小(符号大小),
m_已完成(0)、m_字段(字段)、m_数据(数据)
{
}
...
私人:
uint32\u t m\u符号;
uint32\u t m\u符号\u尺寸;
uint32已完成;
fifi::api::字段m_字段;
std::mutex m_mutex;
std::向量m_数据;
std::向量m_结果;
std::矢量m_编码器;
};
}

您的类可能包含一个互斥体作为成员,但是您的类自动不可复制,因为互斥体不可复制,互斥体现在是类的一部分

所以,无论您在哪里复制类(在您没有向我们展示的代码中),您都不能再这样做了

出于同样的原因,您的类现在也不可移动


如果这是一个问题,您可以将互斥锁隐藏在共享指针之类的东西后面。然而,我会担心共享指针的同步,所以尽量不要…

为了复制包含互斥的对象,您必须编写自定义的复制构造函数和复制赋值操作符

复制对象时不需要复制互斥体,因为互斥体不是对象值的一部分,它只是作为保护访问的工具

复制时,需要使用两个对象的互斥体在复制期间保护值成员

例如:

class simple_encoder
{
public:

    simple_encoder() {}

    // copy constructor
    simple_encoder(simple_encoder const& other)
    {
        // no need to lock this objec because no other thread
        // will be using it until after construction
        // but we DO need to lock the other object
        std::unique_lock<std::mutex> lock_other(other.m_mutex);

        // safely copy the data
        m_symbols = other.m_symbols;
        m_symbol_size = other.m_symbol_size;
        m_completed = other.m_completed;

        // ... etc...
    }

    // copy assignment operator
    simple_encoder& operator=(simple_encoder const& other)
    {
        if(&other != this)
        {
            // lock both objects
            std::unique_lock<std::mutex> lock_this(m_mutex, std::defer_lock);
            std::unique_lock<std::mutex> lock_other(other.m_mutex, std::defer_lock);

            // ensure no deadlock
            std::lock(lock_this, lock_other);

            // safely copy the data
            m_symbols = other.m_symbols;
            m_symbol_size = other.m_symbol_size;
            m_completed = other.m_completed;

            // ... etc...
        }

        return *this;
    }

private:
    // value data
    uint32_t m_symbols;
    uint32_t m_symbol_size;
    uint32_t m_completed;

    // non value utility
    mutable std::mutex m_mutex; // needs to be mutable
};
class简单编码器
{
公众:
简单_编码器(){}
//复制构造函数
简单编码器(简单编码器常数和其他)
{
//不需要锁定此对象,因为没有其他线程
//将一直使用到施工结束
//但我们确实需要锁定另一个对象
std::unique_lock lock_other(other.m_mutex);
//安全地复制数据
m_符号=其他m_符号;
m_symbol_size=其他.m_symbol_size;
m_completed=其他m_completed;
//……等等。。。
}
//复制赋值运算符
简单编码器和运算符=(简单编码器常量和其他)
{
如果(&其他!=此)
{
//锁定两个对象
std::unique_lock lock_this(m_mutex,std::defer_lock);
std::unique_lock lock_other(other.m_mutex,std::defer_lock);
//确保没有死锁
锁(锁这个,锁其他);
//安全地复制数据
m_符号=其他m_符号;
m_symbol_size=其他.m_symbol_size;
m_completed=其他m_completed;
//……等等。。。
}
归还*这个;
}
私人:
//价值数据
uint32\u t m\u符号;
uint32\u t m\u符号\u尺寸;
uint32已完成;
//非价值效用
mutable std::mutex m_mutex;//需要是可变的
};
也可以编写类似的函数来移动对象


如果您有
C++14
,您可以使用
std::shared_timed_mutex
并在复制期间锁定其他对象时替换
std::shared_lock
,这应该会更有效。在移动时,您仍然需要在这两个选项上设置
std::unique\u lock

应该注意的是
std::mutex
也不可移动,所以您仍然需要将其放在指针上以使其可移动。@NathanOliver:Dang是吗not@LightnessRacesinOrbit非常感谢:)此外,您不必在需要时复制/移动互斥体正在复制/移动对象,但您确实需要编写一个自定义的复制分配运算符obvs。@LarsNielsen:不急。不妨看看你还能得到什么。你为什么要抄你的课?