添加 atomic<double> 和 double

3

我想要将两个值相加:

auto size = new std::atomic<double>(0);
double packet_size = 64e3;
*size += packet_size;

但是我遇到了一个错误。

no match for ‘operator+=’ (operand types are ‘std::atomic<double>’ and ‘double’)

我应该如何正确地将这两个数字相加?


4
您好,std::atomic<Floating> 直到 C++20 才出现。您使用的编译器支持它吗? - DeiDei
@DeiDei; 不是在抱怨... http://coliru.stacked-crooked.com/a/24b749dce3f8d705 - user1810087
你可能想看一下这个答案 https://dev59.com/BWAg5IYBdhLWcg3w1t9a - Emerald Weapon
2
@user1810087 这里使用了 operator+,因此它会将 atomic<double> 隐式转换为 double,将它们相加,并将结果赋回原子变量。这有点不是原子性的。 - DeiDei
1
新的...?为什么是那个? - user2672107
显示剩余3条评论
1个回答

2

尽管您可以创建atomic<float>atomic<double>,但浮点原子操作并未定义。这是因为在x86(或ARM)汇编指令中没有原子地添加浮点值的指令。

解决方法是使用compare_exchange操作来增加/更改您的原子变量。

#include <atomic>

int main()
{
    std::atomic<int> i{};
    i += 3;

    //  Peter Cordes pointed out in a comment below that using 
    //  compare_exchange_weak() may be better suited for most 
    //  uses.
    //  Then again, the needed strength of the exchange depends 
    //  on your application, and the hardware it's intended to run on.  

    std::atomic<double> f{};
    for (double g = f; !f.compare_exchange_strong(g, g + 1.0);)
      ;
    return 0;
}

2
如果您已经在使用循环,则使用 compare_exchange_weak ,以便在像 ARM 这样的 LL/SC ISA 上可以更好地编译。否则,这将在 ARM 上编译为嵌套循环。像大多数 RISC 一样,ARM 没有指令来执行除了配对的加载/存储条件外的任何原子 RMW,其中 ALU 操作可以按您想要的方式实现。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接