在Scott Meyers的“有效的现代C++”中,他写道:



在这里,他在解释为什么应该保护对类的const成员变量的访问(在多线程时)的上下文中,将std::mutex m作为成员变量添加到类Polynomial中。我理解他解释的概念。但是我需要更多解释的一件事是“为什么在类中添加仅移动类型使该类成为仅可复制的移动类型”?为什么默认情况下像std::mutexstd::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/

10-12 23:56