В соответствии с этот префикс 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
вести себя иначе, чем встроенные типы в этом отношении?
если 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
это сделает две вещи
Это две совершенно независимые операции. Если другой поток вызывает next
между ними вы получите неправильное значение для вашего поля автоинкремента!
В соответствии с [C++11: 29.6.5/32]
а также [C++11: 29.6.5/10]
, да, cppreference.com правильно в этом отношении.
Я не компетентен, чтобы сказать вам, почему.