简体   繁体   中英

Does std::atomic::operator++ really return by value?

According to this prefix std::atomic<T>::operator++ returns a T , so this code only increments v once:

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

Also, std::atomic<T>::operator= apparently returns a T , so this code dereferences an invalid pointer that used to point to a temporary T :

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

I am most certainly not suggesting that these code patterns are good practice, however it is highly surprising to me that std::atomic breaks them. I always expect operator= and prefix operator++ to return a reference to *this .

Question: Is cppreference right about the return types here, and if so, is there a good reason for having std::atomic behave differently than built-in types in this regard?

if operator++ returned a reference, it would have been a reference to std::atomic<T> not to T in which case you would need to do an additional load to get the current value.

Imagine you've got a DBMS and you need to maintain an 'autoincrement' field

With operator++ retuning T you can do this

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

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

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

Now imagine operator++ returns std::atomic<T>& In that case when you do return ++current it will do two things

  1. Atomic read-modify-write
  2. Atomic load

They are two totally independent operations. If other thread calls next in between you will get wrong value for your autoincrement field!

According to [C++11: 29.6.5/32] and [C++11: 29.6.5/10] , yes, cppreference.com is correct in this regard.

I'm not qualified to tell you why.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM