由于 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_token
和 std::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/