【问题标题】:Can't have Boost::mutex as private class member when using with std::deque?与 std::deque 一起使用时,不能将 Boost::mutex 作为私有类成员吗?
【发布时间】:2012-06-04 02:57:34
【问题描述】:

我在使用 deque 和 boost::mutex 时遇到了一些问题,我做了一个简单的示例,编译时会出现以下错误。

问题是我想拥有一个具有一个或多个互斥锁作为私有成员的类的双端队列。尽管目前该示例给出了错误:

错误 C2248:“boost::mutex::mutex”:无法访问在“boost::mutex”类中声明的私有成员

我看过一些相关的帖子,但到目前为止我还没有设法解决这个具体问题。

任何帮助将不胜感激...

#include <iostream>  
#include <boost/thread.hpp>  
#include <deque>  

using namespace std;

class object {
public:
    void process(void)
    {
        m_mutex.lock();
        // do something
        a = a*10;
        m_mutex.unlock();
    }
    object(int v){  a = v; }        
private:
    int a;
    boost::mutex m_mutex;
};

int main(int argc, char* argv[])  
{
    deque<object> obj; 

    obj.push_back( object( 1 ) );
    obj.push_back( object( 2 ) );
    obj.push_back( object( 3 ) );

    obj.at(0).process();
    obj.at(1).process();
    obj.at(2).process();

    return 0;  
};

【问题讨论】:

  • 您应该使用范围锁类型而不是手动调用锁定/解锁

标签: c++ multithreading boost boost-thread deque


【解决方案1】:
obj.push_back( object( 1 ) );

上面的行创建了一个临时的object 实例,然后将其复制构造到双端队列元素中。由于boost::mutex 不可复制构造,因此编译器无法为object 合成复制构造函数。

如果这是您需要 object 进行复制构造的唯一地方,请将语句更改为

obj.emplace_back( 1 );

emplace_back 导致object 实例在适当的位置构造,而不是使用复制构造。


如果您无权访问 C++11 功能,请将 object 类更改为以下内容:

#include <memory>

class object {
public:
    void process(void)
    {
        m_mutex->lock();
        // do something
        a = a*10;
        m_mutex->unlock();
    }
    object(int v)
    : m_mutex( std::make_shared<boost::mutex>() )
    {  
      a = v; 
    }     

private:
    int a;
    std::shared_ptr<boost::mutex> m_mutex;
};

在 VS2008 中,您可能必须改用 std::tr1::shared_ptr

【讨论】:

    【解决方案2】:

    如果您不想费心编写复制构造函数来避免复制互斥体,则可以改用 Boost 中的 Pointer Container

    例如:

    #include <boost/ptr_container/ptr_deque.hpp>
    ...
    boost::ptr_deque<object> obj;
    obj.push_back(new object());
    obj[0].process()
    ...
    

    现在双端队列的行为与普通双端队列一样,但它从不尝试复制任何 object 实例。

    【讨论】:

      【解决方案3】:

      您不能复制互斥体,因此您也不能复制包含互斥体的类。作为替代方案,您可以为您的班级创建一个 unique_ptrs 的双端队列

       std::deque<std::unique_ptr<object>> obj;
      

      【讨论】:

      • 这看起来不错,但它似乎不是 VS2008 下的选项,仅在使用 #include 的较新 STL 中 - 这听起来对吗?
      • @AlexS 您可以使用 boost::shared_ptr 作为权宜之计解决方案。或者,由于您对对象的使用似乎非常本地化,因此可以选择原始指针。
      • @juanchopanza 谢谢,但如果使用 boost 似乎 Inverse 的解决方案是最直接的。
      【解决方案4】:

      互斥锁不是 CopyConstructible,因此您的类型的复制构造函数格式不正确。

      您可以提供一个不复制互斥锁的用户定义的复制构造函数。

      【讨论】:

      • 嗨,我应该提到我已经从我阅读的帖子中意识到了这一点,但是如何解决呢?
      • 自定义复制构造函数会是什么样子?我不明白。
      • 通过在自定义复制构造函数中省略互斥体副本,您可能会避免一个问题并创建另一个问题。如果一个线程获得了锁,而另一个线程对deque 做了一些需要复制对象的操作怎么办?
      • object(const object& o) : a(o.a) {}
      • 是的,也不是没有问题,但是小心点还是可以用的。
      猜你喜欢
      • 2017-03-21
      • 1970-01-01
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多