简体   繁体   English

使用 std::mutex 复制类

[英]Copy Class with std::mutex

I have a class with a std::mutex as a member.我有一个以 std::mutex 作为成员的类。 I am trying to create an array of such class我正在尝试创建此类类的数组

class C
{
 int x;
 std::mutex m;
};

int main()
{
  C c[10];
  //later trying to create a temp C
  C temp = c[0];
}

Clearly the above is not possible as mutex object is not copyable.显然以上是不可能的,因为互斥对象是不可复制的。 The way to solve it is through a copy constructor.解决它的方法是通过复制构造函数。

However, I am having problem in creating a copy constructor.但是,我在创建复制构造函数时遇到问题。 I have tried我努力了

C (const C &c)
{
   x = c.x;

   //1. m
   //2. m()
   //3. m = c.m
}

I am not sure what is the right syntax out of the 3 choices.我不确定这 3 个选择中的正确语法是什么。 Please help.请帮忙。

You shouldn't write any of these lines.你不应该写任何这些行。 Your implementation of copy constructor is equivalent to:您对复制构造函数的实现等效于:

C (const C &c) : x(), m()
{
   x = c.x;
}

So new instance of mutex m is default initialized which means that one of the default constructors will be called.因此,mutex m的新实例被默认初始化,这意味着将调用默认构造函数之一。 It may be safely used.它可以安全使用。

However, there are several conserns about this code.但是,关于此代码有几个问题。 Ie if m protects x , you should explicitly lock it before accessing value:即如果m保护x ,您应该在访问值之前显式锁定它:

C (const C &c)
{
    std::lock_guard<std::mutex> guard(c.m);
    x = c.x;
}

which would require to declare m as mutable (because c is const reference in copy ctor).这需要将m声明为可变的(因为c是复制 ctor 中的 const 引用)。

mutable std::mutex m;

In the end, you can see that copying objects with mutexes inside is confusing, and if C is public class, it'll confuse its users, so think twice before implementing copying of it.最后,您可以看到复制带有互斥锁的对象是令人困惑的,如果C是公共类,它会混淆它的用户,所以在实现它的复制之前要三思而后行。

Short answer you dont copy the mutex.简短的回答你不复制互斥锁。

Lets start from the basics, mutex is a short name of mutual exclusion ie you want to make sure that, when there are multiple threads you dont want them to change/modify the value in parallel.让我们从基础开始,互斥锁是互斥的简称,即您要确保,当有多个线程时,您不希望它们并行更改/修改值。 You want to serialize the access or modification/read so that the value read is valid.您想要序列化访问或修改/读取,以便读取的值有效。

In the above case you are copying a new value to the variable.In this case you need not use a mutex lock as you are creating a new object.在上述情况下,您正在将新值复制到变量中。在这种情况下,您无需使用互斥锁,因为您正在创建新对象。

您可以使用shared_ptr<C>的数组,然后您不需要C本身是可复制的......

std::mutex m does not have to be copied. std::mutex m 不必复制。 You can use the default constructed mutex.您可以使用默认构造的互斥锁。

As stated in other answers, there are only pretty niche situations in which you would want to do this, but in the case that you have some object class that uses a mutex internally, you will want to make copy and move constructors that explicitly declare everything to move and copy except for the mutex.正如其他答案中所述,只有在非常小众的情况下您想要这样做,但是如果您有一些在内部使用互斥锁的对象类,您将需要复制和移动显式声明所有内容的构造函数移动和复制,互斥锁除外。 This will result in the mutex (and anything else left out) being default constructed (ie each new or copied object will get its own unique mutex).这将导致互斥体(以及任何其他遗漏)被默认构造(即每个新的或复制的对象都将获得自己唯一的互斥体)。 Make sure that whatever your mutex is used to protect from is not being called while using the copy or move constructors as they do not (can not?) call the mutex to lock.确保在使用复制或移动构造函数时不会调用任何用于保护的互斥锁,因为它们不会(不能?)调用互斥锁来锁定。

Here is a full example to help anyone in the future running into this issue:这是一个完整的示例,可以帮助将来遇到此问题的任何人:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM