【问题标题】:Does std::atomic::operator++ really return by value?std::atomic::operator++ 真的按值返回吗?
【发布时间】:2012-10-25 05:25:53
【问题描述】:

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

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

另外,std::atomic&lt;T&gt;::operator= apparently 返回一个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 在这方面与内置类型的行为不同?

【问题讨论】:

  • 如果operator= 返回T,那么&amp;(v = 1) 甚至不应该编译,对吧?
  • @R.MartinhoFernandes:因为它是临时的右值?
  • 它是否返回左值?如果不是,那么第二个 ++ 将无法编译,因此如果您确实希望这样做,至少可以避免出现错误行为。
  • @LightnessRacesinOrbit 因为它是prvalue。所以,是的,一些原子操作可能会按值返回,这与常见用法相反,但只有糟糕的编译器才会允许编译这些示例中的任何一个。
  • 错误的编译器,或(不太可能)错误的类型 T 专门用于 std::atomic 并且前缀 operator++ 是可以绑定到右值的成员函数。但是,如果您专门针对您的用户定义类型使用 std::atomic,那么您真的应该非常了解 std::atomic,知道不要这样做。

标签: c++ c++11 operator-overloading atomic c++-standard-library


【解决方案1】:

如果operator++ 返回了一个引用,它应该是对std::atomic&lt;T&gt; 的引用而不是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&lt;T&gt;&amp; 在这种情况下,当您执行 return ++current 时,它会做两件事

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

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

【讨论】:

  • +1。简而言之,这是因为 atomic (increment and return the new value) 比 (atomic increment) 和 (return a reference to the atomic object) 有用得多,所以设计者觉得它证明了稍微令人惊讶的返回类型是合理的。
  • 请不要通过编辑破坏您的答案。这已被回滚。
【解决方案2】:

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

我没有资格告诉你原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2019-02-19
    • 2012-06-14
    • 2016-12-16
    • 2019-03-22
    • 1970-01-01
    • 2015-05-10
    相关资源
    最近更新 更多