c++ - "const std::stop_token&"或者只是 "std::stop_token"作为线程函数的参数?

标签 c++ multithreading c++20

由于 clang-tidy 提示“每次调用都会复制参数‘stop_token’,但仅用作 const 引用;考虑将其设为 const 引用”,我在问自己这个问题,为什么我找到的每个示例都是关于 std 的::jthread/stop_token 按值获取 stop_token,但我没有找到任何解释。

那么,为什么要按值取 stop_token?

1) void f(std::stop_token){};
2) void f(const std::stop_token&){};

当您可以假设 stop_token 是由 std::jthread 生成的时,这真的很重要吗?

编辑:这纯粹是出于好奇,不要“仅仅因为”而忽略 clang-tidy 警告。

最佳答案

根据 cppref ,

Creates new jthread object and associates it with a thread of execution. The new thread of execution starts executing

std::invoke(std::move(f_copy), get_stop_token(), std::move(args_copy)...), ...

以及std::jthread::get_stop_token的返回类型是 std::stop_token

因此,如果您的f 仅用于构建std::jthread,我相信完全可以 const std::stop_token& 作为它的第一个参数。没有生命周期问题。

但是如果你想在其他地方使用你的f,例如std::thread,可能会有问题。

void f(const std::stop_token&) {}
{
    std::stop_source ssrc;
    std::stop_token stk{ssrc.get_token()};
    std::thread t{f, std::ref(stk)};
}

stk 被销毁时,引用是悬挂的。


大多数情况下,您应该按值传递。

因为复制 std::stop_tokenstd::stop_source 相对便宜。
此外,由于 std::token 通常存储在 lambda 中和/或在另一个线程中使用,因此按值传递可以避免生命周期问题。

还有一些情况下您可以通过引用传递。

因为与原始指针相比它并不便宜。如果能保证生命周期,引用传递效率会更高。

例如,std::stop_callback's constructor , 因为它会将 std::stop_token 复制到里面,所以通过引用传递会更好。

template<class C>
explicit stop_callback( const std::stop_token& st, C&& cb ) noexcept(/*see below*/);

关于c++ - "const std::stop_token&"或者只是 "std::stop_token"作为线程函数的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72990607/

相关文章:

c++ - 这应该是 constexpr 还是不?

c++ - 编译包装器时出现 SWIG [C++ to Lisp(CFFI)] 错误

c++ - 沿平面剪切后填充网格孔

c++ - 在 windows linux 子系统上交叉编译并使用 Visual Studio 2017 部署到目标

c++ - 从运行 QML QtQuick2 引擎的不同线程更新 c++ 模型的行为

c++ 存储函数和参数列表以备后用

java - ArrayList vs HashMap——大量的迭代和对象操作

c++ - MSVC 对 C++20 中闭包类型的默认构造函数的行为有所不同

C++20 使用概念来强制类上的接口(interface)

c++ - Visual Studio 在添加 if 语句后显示 C++ 歧义错误