存储后的std :: atomic地址

问题描述

在存储之后,我似乎无法获得原子对象的地址。

例如

std::atomic<int> i;
std::atomic<int>* p = &++i; // doesn't work
auto* p = &++i; // doesn't work
// below works:
++i;
auto* p = &i;

这里发生了什么,为什么?

为了澄清:我知道它返回一个r值。为什么它不返回原始对象this?这是一个有目的的设计选择还是一个疏忽?

更具体地说,此要求在幕后发生了什么?

解决方法

虽然预递增运算符通常通过引用返回其操作数,但对于std::atomic整数,它会作为临时值返回新值。因此,在您的示例中,++i不会返回对atomic<int> i本身的引用,而是返回i的新值(即int)。您可以在https://en.cppreference.com/w/cpp/atomic/atomic/operator_arith

上看到它

返回对原始atomic<int>的引用将产生误导甚至危险,因为通过此引用访问int值将需要秒的单独读取操作-因此,值可能与增量时的值不同。 (这与示例代码并不特别相关,因为您仅尝试获取指向所引用对象的指针,但是某些代码实际上会访问++之后的值,因此这就是为什么无法返回引用的原因)

换句话说,如果++i返回了对atomic<int> i的引用,则

int j = ++i;

将等同于

++i;
// ...other threads may modify the value of `i` here!...
int j = i;

原子的全部要点是作为不可分割的操作一起执行读取和写入操作,因此++i必须在内部使用硬件/ OS原子操作来同时读取和递增整数,因此新值将返回为

如果您想知道问题的根源,可以在here is libc++'s implementation处看到operator++只需调用fetch_add(1)并返回结果+ 1。