我有一个以std :: mutex为成员的类。我正在尝试创建一个这样的类
的数组class C
{
int x;
std::mutex m;
};
int main()
{
C c[10];
//later trying to create a temp C
C temp = c[0];
}
显然,由于互斥对象不可复制,因此无法实现上述目的。解决问题的方法是通过复制构造函数。
但是,我在创建复制构造函数时遇到问题。我试过了
C (const C &c)
{
x = c.x;
//1. m
//2. m()
//3. m = c.m
}
我不确定3种选择中的正确语法是什么。请帮忙。
答案 0 :(得分:8)
你不应该写任何这些行。您的拷贝构造函数的实现等同于:
C (const C &c) : x(), m()
{
x = c.x;
}
因此互斥m
的新实例是default initialized,这意味着将调用其中一个默认构造函数。它可以安全使用。
但是,有几个关于此代码的内容。即如果m
保护x
,则应在访问值之前明确锁定它:
C (const C &c)
{
std::lock_guard<std::mutex> (c.m);
x = c.x;
}
这需要将m
声明为可变(因为c
是复制ctor中的const引用)。
mutable std::mutex m;
最后,您可以看到复制具有互斥锁的对象是令人困惑的,如果C
是公共类,它会使用户感到困惑,所以在实现复制之前要三思而后行。
答案 1 :(得分:7)
简短的回答你不要复制互斥锁。
让我们从基础开始,互斥是一个互斥的简称,即你要确保当有多个线程时你不希望它们并行更改/修改值。您希望序列化访问或修改/读取,以便读取的值有效。
在上面的例子中,您将一个新值复制到变量。在这种情况下,您不需要在创建新对象时使用互斥锁。
答案 2 :(得分:4)
您可以使用shared_ptr<C>
数组,然后您不需要C
本身可以复制......
答案 3 :(得分:1)
std :: mutex m不必复制。您可以使用默认构造的互斥锁。
答案 4 :(得分:1)
如其他答案中所述,在某些特殊情况下,您需要执行此操作,但是如果您有一些对象类在内部使用互斥量,则需要复制并移动构造函数,明确声明所有要移动和复制的内容(互斥锁除外)。这将导致互斥锁(以及其他遗漏的东西)被默认构造(即,每个新对象或复制对象将获得自己的唯一互斥锁)。确保在使用复制或移动构造函数时不会调用您用来保护互斥对象的任何东西,因为它们不会(不能?)调用互斥对象进行锁定。
这是一个完整的示例,可以帮助以后遇到此问题的任何人:
class Shape
{
public:
Shape() {} //default constructor
Shape(double _size) //overloaded constructor
{
size = _size;
}
Shape(const Shape& obj) //copy constructor (must be explicitly declared if class has non-copyable member)
{
//Do not put any non-copyable member variables in here (ie the mutex), as they will be
//default initialized if left out
size = obj.size; //any variables you want to retain in the copy
}
Shape& operator=(const Shape&& obj) //move constructor (must be explicitly declared if class has non-copyable member)
{
//Do not put any non-copyable member variables in here (ie the mutex), as they will be
//default initialized if left out
size = obj.size;//any variables you want to retain in the move
return *this;
}
double testMe() { return size; }
private:
std::mutex dataMutex;
double size;
};