c++操作符=类成员中有互斥对象

C++ operator= with a mutex in class member

本文关键字:对象 成员 操作符 c++      更新时间:2023-10-16

我有一个类,其中包含一些变量,比如一个列表和一个布尔值,可以由几个线程编写,并由它们自己的互斥锁保护:

class Motel
{
// [...]
private:
    list<Room> _rooms;
    boost::mutex _rooms_mtx;
    bool _opened;
    boost::mutex _opened_mtx;
}

这段代码的问题是,当我需要复制构造函数或操作符=(即使是自动生成的)时,在我的情况下,我想把类放在一个映射中:

boost::map<string, Motel> all_motels;
Motel grenoble(...);
all_motels["Grenoble"] = grenoble;

这是禁止的,因为不能复制互斥锁:

/usr/include/boost/thread/pthread/mutex.hpp: In copy constructor ‘project::Motel::Motel(const project::Motel&)’:
/usr/include/boost/thread/pthread/mutex.hpp:33:9: error: ‘boost::mutex::mutex(const boost::mutex&)’ is private
在这种情况下我该怎么做?提前感谢

这里常见的解决方案是使Motel不可复制,并与new一起在堆上分配Motel对象。使用boost::noncopyable和智能指针也是一个好主意。

class Motel : private boost::noncopyable
{
// [...]
private:
    list<Room> _rooms;
    boost::mutex _rooms_mtx;
    bool _opened;
    boost::mutex _opened_mtx;
}
boost::map<string, boost::unique_ptr<Motel> > all_motels;
all_motels["Grenoble"].reset(new Motel(...));

您不能复制boost::互斥锁(您的错误消息显示boost阻止了它,但是尝试复制互斥锁是一堆蠕虫)。至少,您必须为Motel编写自己的复制构造函数,并且必须弄清楚如何处理互斥对象。您很可能希望自己创建一个互斥对象。

另一个解决方案是使用互斥指针。

private:
    list<Room> _rooms;
    boost::mutex* _rooms_mtx;
    bool _opened;
    boost::mutex* _opened_mtx;
}

顺便说一下,你必须确保尊重这些问题:

  • 互斥锁会被正确创建吗?
  • 互斥锁是否被正确使用?

您必须提供复制构造函数赋值重载 (operator=),它们不是复制互斥锁,而是复制数据。请看下面的运行示例:

#include <map>
#include <boost/thread/mutex.hpp>

class foo {
public:
    foo() {}
    foo(foo const& cp)
        : data_(cp.data_) {}
    foo& operator=(foo const& cp) {
        data_ = cp.data_;
        return *this;
    }
private:
    boost::mutex mtx_;
    bool data_;
};

int main(int argc, char* argv[]) {
    std::map<int, foo> bar;
    bar[1] = foo();
    return 0;
}

<标题>但h1>
int main(int argc, char* argv[]) {
    std::map<int, std::shared_ptr<foo>> bar; // untested but you see the point
    bar[1] = std::shared_ptr<foo>(new foo); 
    return 0;
}