【问题标题】:std::mutex as class member, and store class obect to containerstd::mutex 作为类成员,并将类对象存储到容器中
【发布时间】:2019-03-05 12:51:33
【问题描述】:

以下是重现错误的最少代码。

#include <iostream>
#include <mutex>
#include <vector>

class A {
    std::mutex mutex;
    public:
    A(){};
};
int main() 
{
    std::vector<std::pair<std::string,A>> aa;
    A a;
    //aa.push_back(std::make_pair(std::string("aa"),A()));
    //aa.push_back(std::make_pair(std::string("aa"),a));
    aa.push_back(std::make_pair(std::string("aa"),std::move(a)));    
}

以下是错误。

Microsoft (R) C/C++ 优化编译器版本 19.16.27026.1 for x64 版权所有 (C) 微软公司。保留所有权利。

>   C:\Program Files (x86)\Microsoft Visual
> Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\xlocale(319):
> warning C4530: C++ exception handler used, but unwind semantics are
> not enabled. Specify /EHsc    C:\Program Files (x86)\Microsoft Visual
> Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\utility(405):
> error C2440: '<function-style-cast>': cannot convert from 'initializer
> list' to '_Mypair'    C:\Program Files (x86)\Microsoft Visual
> Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\utility(405):
> note: No constructor could take the source type, or constructor
> overload resolution was ambiguous
>   ..\examples\json_object\json.cpp(16): note: see reference to function
> template instantiation 'std::pair<std::string,A>
> std::make_pair<std::string,A>(_Ty1 &&,_Ty2 &&)' being compiled            with
>           [
>               _Ty1=std::string,
>               _Ty2=A          ]

gcc 编译器的类似错误。 当我从类中删除 std::mutex 或不将对象推送到 std::vector 时,它可以正常编译。

【问题讨论】:

    标签: c++ c++11 mutex


    【解决方案1】:

    根据std::mutex 上的文档。

    std::mutex 既不能复制也不能移动

    由于类A 包含一个std::mutex 变量mutex,它也不能移动。

    【讨论】:

    • 解决这个问题的方法是使用(智能)指向 std::mutex 的指针。
    【解决方案2】:

    作为 P.W.指出,std::mutex 既不可复制也不可移动,这是有充分理由的。拥有互斥锁的全部意义在于防止同时多线程访问某些数据。移动操作本身需要保护,并且互斥体应该被移动操作使用

    以下示例为类提供了一些可移动数据,并展示了如何在移动操作中使用互斥锁(复制操作类似):

    #include <iostream>
    #include <mutex>
    #include <vector>
    #include <memory>
    
    class A {
    public:
      A() {};
    
      // Move constructor
      A(A&& other) {
        std::lock_guard<std::mutex> guard(other.m_mutex);
        m_data = std::move(other.m_data);
      }
    
      // Move operator
      A& operator=(A&& other) {
        if (this == &other) return *this;
    
        // Lock this and other in a consistent order to prevent deadlock
        std::mutex* first;
        std::mutex* second;
        if (this < &other) {
          first = &this->m_mutex;
          second = &other.m_mutex;
        } else {
          first = &other.m_mutex;
          second = &this->m_mutex;
        }
        std::lock_guard<std::mutex> guard1(*first);
        std::lock_guard<std::mutex> guard2(*second);
    
        // Now both this and other are safe to access.  Do the actual data move.
        m_data = std::move(other.m_data);
        return *this;
      }
    
    private:
      std::mutex m_mutex;
      std::unique_ptr<int> m_data;
    };
    
    int main() {
      std::vector<std::pair<std::string,A>> aa;
      A a1;
      A a2;
      a1 = std::move(a2);
      aa.emplace_back("aa", std::move(a1));
    }
    

    【讨论】:

      【解决方案3】:

      正如 P.W 所指出的和怪胎提供的提示,我想出了以下解决方案。

      #include <iostream>
      #include <mutex>
      #include <vector>
      #include <memory>
      
      class A {
          std::mutex mutex;
          public:
          A(){};
      };
      int main() 
      {
          std::vector<std::pair<std::string,std::shared_ptr<A>>> aa;
          A a;
          //aa.push_back(std::make_pair(std::string("aa"),A()));
          //aa.push_back(std::make_pair(std::string("aa"),a));
          aa.push_back(std::make_pair(std::string("aa"),std::make_shared<A>()));   
      }
      

      我修改了我的容器来存储对象的智能指针而不是对象本身。

      【讨论】:

      • FWIW,你真的应该使用std::unique_ptr,除非你真的需要共享所有权。 90% 的时候,你不会。
      猜你喜欢
      • 2018-08-16
      • 2016-04-28
      • 2011-12-07
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-02
      相关资源
      最近更新 更多