我有一个成员是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个选择。请帮帮我
6条答案
按热度按时间h6my8fg21#
你不应该写这些台词。复制构造函数的实现等效于:
因此,互斥体
m
的新示例是default initialized,这意味着将调用一个默认构造函数。它可以安全地使用。但是,关于此代码有几个conserns。也就是说,如果
m
保护x
,你应该在访问value之前显式地锁定它:这需要将
m
声明为可变的(因为c
在复制ctor中是const引用)。最后,您可以看到复制内部带有互斥锁的对象是令人困惑的,如果
C
是公共类,它会让用户感到困惑,因此在实现复制之前要三思而后行。ct2axkht2#
简短的回答你不复制互斥体。
让我们从基础开始,互斥是互斥的简称,即你要确保,当有多个线程时,你不希望它们并行地更改/修改值。您希望序列化访问或修改/读取,以便读取的值有效。
在上面的例子中,你复制了一个新的值到变量中。在这种情况下,你不需要使用互斥锁,因为你正在创建一个新的对象。
rdrgkggo3#
你可以使用一个
shared_ptr<C>
的数组,那么你就不需要C
本身是可复制的。hpxqektj4#
std::mutex m不需要复制。您可以使用默认构造的互斥体。
rqdpfwrv5#
正如在其他答案中所述,只有在非常小的情况下你才会想要这样做,但是如果你有一些内部使用互斥锁的对象类,你会想要制作复制和移动构造函数,显式声明除了互斥锁之外的所有东西都要移动和复制。这将导致互斥锁(以及其他任何遗漏的东西)被默认构造(即每个新的或复制的对象将获得自己唯一的互斥锁)。确保在使用复制或移动构造函数时,无论您的互斥体是用来防止被调用的,因为它们不会(不能?)调用互斥锁来锁定。
下面是一个完整的例子,以帮助任何人在未来遇到这个问题:
ff29svar6#
以上都是不好的建议,建议你打破rule of zero。
更好的方法是创建一个实用程序类,用于根据您希望应用的规则处理复制互斥锁的问题。例如(这可能不符合您的要求)以下代码
https://godbolt.org/z/Y86jscd6K
演示了一个名为 *mutex_保持器 * 的类型,它遵循复制时副本总是获得新互斥体的规则。您可以将此策略应用于需要复制的某个类中的互斥体
然后当你需要用锁的时候
您可以看到类A是可复制和可移动的,无需编写任何自定义的特殊成员函数构造函数。
如果您需要在复制过程中保护某些成员,也可以实现这样的策略类来实现此目的。
同样,您的业务逻辑类不应该有自定义SMF。让编译器为您编写它们。