std::atomic 作为非原子类型的 const 引用传递

std::atomic passed as a const reference to a non-atomic type

假设我有这个应用程序:

#include <atomic>
#include <thread>
#include <iostream>
#include <chrono>

void do_something(const std::atomic<bool>& stop) {
    while (!stop) {
        std::cout << "Doing stuff..." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

int main() {
    std::atomic<bool> stop { false };

    std::thread wait([&stop] { 
        std::this_thread::sleep_for(std::chrono::seconds(10));
        stop = true;
    });

    do_something(stop);

    wait.join();
}

这按预期工作。主线程循环直到 wait 线程设置 stop。据我所知,这个应用程序没有真正的问题,因为它使用 std::atomic<bool> 来实现线程之间的同步。

但是,我可以通过将 do_something 的签名更改为这样来破坏应用程序:

void do_something(const bool& stop);

这仍然可以在没有任何警告的情况下编译,但是 do_something 中的循环永远不会退出。从概念上讲,我理解为什么会这样。 do_something 正在接受对非原子值的 const 引用,因此将函数优化为类似以下内容是合理的:

void do_something(const bool& stop) {
    if (!stop) {
        while(true) {
            std::cout << "Doing stuff..." << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
}

令我困惑的是为什么修改后的应用程序完全可以编译。我不希望能够将 std::atomic 值传递给期望对非原子类型的 const 引用的函数。我没有看过标准,但我在 cppreference 上没有看到任何表明允许这种转换的内容。

我是不是误会了什么?这只是 std::atomic 的一些怪癖,我从文档中看不出吗?

这是因为你调用的时候有隐式转换 do_something(const bool &stop) 通过 std::atomic<bool>

翻译成:

do_something(static_cast<bool>(stop.operator bool()));

如您所见:https://en.cppreference.com/w/cpp/atomic/atomic/operator_T

您实际上告诉编译器加载一次值,就在调用时。