14

根据这个前缀std::atomic<T>::operator++返回 a T,所以这段代码只增加v一次:

template<class T> void addTwo(std::atomic<T>& v) {
  ++(++v);
}

此外,std::atomic<T>::operator= 显然返回 a T,因此此代码取消引用一个用于指向临时的无效指针T

template<class T>
void setOneThenTwo(std::atomic<T>& v) {
  auto ptr = &(v = 1);
  *ptr = 2;
}

我绝对不是说这些代码模式是好的实践,但是std::atomic打破它们对我来说是非常令人惊讶的。我总是期望operator=和前缀operator++返回对*this.

问题: cppreference 关于这里的返回类型是否正确,如果是,是否有充分的理由std::atomic在这方面与内置类型的行为不同?

4

2 回答 2

21

如果operator++返回一个引用,它将是一个对std::atomic<T>not的引用,T在这种情况下,您需要做一个额外load的操作来获取当前值。

想象一下,你有一个 DBMS,你需要维护一个“自动增量”字段

通过 operator++重新调整T,您可以做到这一点

class AutoIncrement
{
public:
   AutoIncrement() : current (0) {}

   unsigned int next()
   {
      return ++current;
   }

private:
   std::atomic<unsigned int> current;
};

现在想象operator++返回std::atomic<T>& 在那种情况下,当你这样做时,return ++current它会做两件事

  1. 原子读-修改-写
  2. 原子负载

它们是两个完全独立的操作。如果您之间的其他线程调用next将为您的自动增量字段获得错误的值!

于 2012-11-05T11:36:35.380 回答
2

根据[C++11: 29.6.5/32]and [C++11: 29.6.5/10],是的,cppreference.com在这方面是正确的。

我没有资格告诉你为什么。

于 2012-11-05T11:24:07.530 回答