33

我有一个带有原子成员变量的类:

struct Foo
{
  std::atomic<bool> bar;
  /* ... lots of other stuff, not relevant here ... */
  Foo() 
  : bar( false )
  {}

  /* Trivial implementation fails in gcc 4.7 with:
   *   error: use of deleted function ‘std::atomic<bool>::atomic(const td::atomic<bool>&)’
   */
  Foo( Foo&& other )
  : bar( other.bar )
  {}
};

Foo f;
Foo f2(std::move(f));  // use the move

移动构造函数应该如何?

Gcc 4.7 不喜欢我的任何尝试(比如std::move()在 周围添加other.bar),而且这里的网络出奇地安静......

4

3 回答 3

32

std::atomic不可复制或可移动,因为它的复制构造函数被删除并且没有定义移动构造函数。您必须显式加载另一个值并使用它来构造新值,正如 gustaf 的回答中所指出的那样。

为什么std::atomic不能移动?由于它是一个同步原语,所有线程必须在相同的数据(即相同的地址)上进行同步。当你复制(或移动)一个原子值时,你必须使用一些通信协议。它可能很简单,就像在您的示例中一样(只需加载它并使用它来初始化新的原子),但总的来说,我认为 C++11 强制您考虑它是一个很好的设计决策。否则,它可能会导致代码看起来不错,但存在一些细微的同步问题。

于 2013-01-06T14:21:03.297 回答
19

由于您要搬家other,因此没有其他人可以访问它。所以从它读取bar是安全的,不管它是不是原子的。

atomic<T>只有两个构造函数,一个是 default (),另一个是(T). 因此,您的代码看起来应该可以编译。如果没有,如果你 static_cast other.bartoT强制使用(T)构造函数会发生什么?

: bar( static_cast< bool >( other.bar ) )

或等于,也许不那么难看:

: bar( other.bar.load( ) )

于 2013-01-06T13:05:54.917 回答
2

的模板实例化atomic<bool>基本上如下所示:

struct atomic<bool>
{
    atomic<bool>(bool);
    atomic<bool>( const atomic<bool>& ) = delete;
    operator bool() const;
}

因此,当您尝试复制它时:

atomic<bool> a = ...;
atomic<bool> b(a);

选择了已删除的复制构造函数并导致编译错误。

您需要显式转换为 bool 才能通过operator bool() --> atomic<bool>(bool)...

atomic<bool> a = ...;
atomic<bool> b(bool(a));
于 2013-01-06T15:46:23.407 回答