代码之家  ›  专栏  ›  技术社区  ›  Manthan Tilva

std::mutex作为类成员,并将类obect存储到容器

  •  1
  • Manthan Tilva  · 技术社区  · 6 年前

    下面是再现错误的最小代码。

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

    下面是错误。

    X64的微软(R)C/C++优化编译器版本19.16.217021.1 版权所有(c)Microsoft Corporation。保留所有权利。

    >   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 ,然后它编译得很好。

    1 回复  |  直到 6 年前
        1
  •  7
  •   P.W    6 年前

    根据文件 std::mutex 是的。

    std::互斥 两者都不可复制 不可移动 是的。

    下课后 A 包含一个 std::互斥 变量 mutex ,它也不能移动。

        2
  •  1
  •   Jay West    6 年前

    正如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
  •  0
  •   Manthan Tilva    6 年前

    正如P.W所指出的和Freakish所提供的提示,我提出了下面的解决方案。

    #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>()));   
    }
    

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