C ++ 11:使用atomic <bool>成员编写移动构造函数?</bool>

时间:2013-01-06 12:46:34

标签: c++ c++11 atomic move-semantics libstdc++

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

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),网络在这里非常安静......

3 个答案:

答案 0 :(得分:25)

std::atomic不可复制或移动,因为its copy constructor is deleted并且未定义移动构造函数。您必须显式加载其他值并使用它构造新值,正如gustaf的回答中所指出的那样。

为什么std::atomic无法移动?由于它是同步原语,所有线程必须在相同的数据(即,相同的地址)上同步。复制(或移动)原子值时,必须使用某种通信协议。它可能很简单,就像在您的示例中一样(只需加载它并使用它来初始化新原子)但是,一般来说,我认为C ++ 11强制设计决定迫使您去思考它。否则,它可能会导致代码看起来很好,但是会出现一些严重的同步问题。

答案 1 :(得分:16)

由于您正在移动other,因此没有其他人可以访问它。因此从bar读取是安全的,不管是原子还是非原子。

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

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

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

: bar( other.bar.load( ) )

答案 2 :(得分:1)

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