代码之家  ›  专栏  ›  技术社区  ›  Lars Nielsen

如何将互斥体用作成员变量?“simple\u encoder”的无复制构造函数被隐式删除

  •  5
  • Lars Nielsen  · 技术社区  · 6 年前

    您好,我正在尝试创建一个多线程编码器,它需要一个互斥体,我希望该互斥体成为该类的成员。然而,我不断得到: copy constructor of 'simple_encoder' is implicitly deleted because field 'm_mutex' has an inaccessible copy constructor 作为编译时的错误消息。经过一个小时的搜寻,我找不到我的错误。

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

    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;
    };
    }
    
    2 回复  |  直到 6 年前
        1
  •  14
  •   Galik    6 年前

    为了复制包含 互斥体 您必须编写自定义 复制构造函数 复制分配运算符 .

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

    复制时,的互斥体 二者都 需要使用对象来保护 值成员 在复制过程中。

    例如:

    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
    };
    

    也可以为编写类似的函数 移动 对象。

    如果你有 C++14 您可以使用 std::shared_timed_mutex 并替换为a std::shared_lock<std::shared_timed_mutex> 锁定时 另外 对象进行复制,这应该更有效。你还需要 std::unique_lock 移动 .

        2
  •  1
  •   Lightness Races in Orbit Shash316    6 年前

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

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

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

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