Действительно ли std :: atomic :: operator ++ возвращает значение?

В соответствии с этот префикс std::atomic<T>::operator++ возвращает Tтак что этот код только увеличивается v один раз:

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

Также, std::atomic<T>::operator= по-видимому возвращает 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 вести себя иначе, чем встроенные типы в этом отношении?

13

Решение

если operator++ вернул ссылку, это была бы ссылка на std::atomic<T> не для T в этом случае вам нужно будет сделать дополнительный load чтобы получить текущее значение.

Представьте, что у вас есть СУБД, и вам нужно поддерживать поле автоинкремента

С 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 между ними вы получите неправильное значение для вашего поля автоинкремента!

20

Другие решения

В соответствии с [C++11: 29.6.5/32] а также [C++11: 29.6.5/10], да, cppreference.com правильно в этом отношении.

Я не компетентен, чтобы сказать вам, почему.

2

По вопросам рекламы [email protected]