在Scott Meyers的“有效的现代C++”中,他写道:
在这里,他在解释为什么应该保护对类的const成员变量的访问(在多线程时)的上下文中,将std::mutex m
作为成员变量添加到类Polynomial
中。我理解他解释的概念。但是我需要更多解释的一件事是“为什么在类中添加仅移动类型使该类成为仅可复制的移动类型”?为什么默认情况下像std::mutex
和std::atomic
这样的类型是仅移动类型?即使要向类中添加仅移动类型的变量,也要执行复制操作,如何克服它呢?
最佳答案
std::mutex
不能复制仅是因为该标准如此规定。他们可能编写了可复制的std::mutex
,但他们决定不这样做。
猜测,不可复制的std::mutex
可能更有效,更安全或更容易理解。
例如,这就是为什么更安全/更容易理解的原因:复制已锁定的std::mutex
是什么意思?我个人不知道正确的答案是什么。我怀疑正确的答案是“那是胡扯”。没有“最不惊奇的答案”。
通过阻止复制,我们不会在并发代码中得到令人惊讶的答案,而是避免了这个问题。存储互斥量的人要复制就必须自己决定要做什么。
C++在某些情况下会自动生成一个副本构造函数。在更多情况下,它将允许您执行MyClass(MyClass const&)=default
并在需要时编写一个。
如果您的类(class)包含不可复制的类(class),则不会生成一个,并且您无法要求它。这是因为生成的副本构造函数基本上会复制其成员。如果无法复制成员,则无法生成复制构造函数。
因此mutex
无法复制,因为该标准要求如此。
如果结构或类包含不可复制的成员,则不能使用默认的复制构造函数。您必须自己明确地写一个人。
如果您的类型需要存储mutex
,则可以避免将手动维护其所有其他成员的副本ctor麻烦的一种方法是将非mutex
状态粘贴到子结构中,然后使用其默认副本。然后,您决定在复制期间如何处理mutex
,并且复制ctor(和赋值复制运算符)仍然很简单。
struct bob_with_mutex {
sturct bob_simple_data {
int x, y, z;
std::vector<char> buff;
};
bob_simple_data data;
std::mutex m;
bob_with_mutex( bob_with_mutex const& o ):
data(o.data)
{}
bob_with_mutex& operator=( bob_with_mutex const& o )
{
data = o.data;
return *this;
}
};
bob
类型包含互斥量和一些数据。数据存储在子结构中。不能将bob_with_mutex
的副本ctor设置为默认值,而只是说“复制数据,没有其他内容”。bob
的副本具有自己的互斥量。关于c++ - 在类中添加仅移动类型会使该类成为仅移动类型?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36284938/