由于 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 生成的时,这真的很重要吗?
编辑:提出这个问题纯粹是出于好奇,并且不要忽视“只是因为”的铿锵有力的警告。
根据cppref,
创建新的 jthread 对象并将其与执行线程关联。新的执行线程开始执行
,...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::stop_token
通常存储在 lambda 中和/或在另一个线程中使用,因此按值传递可以避免生命周期问题。
也有一些情况你可以通过引用传递。
因为与原始指针相比,它并不便宜。如果能保证生命周期的话,通过引用传递会更高效。
std::stop_callback
的构造函数,因为里面会复制std::stop_token
,所以通过引用传递会更好。
template<class C>
explicit stop_callback( const std::stop_token& st, C&& cb ) noexcept(/*see below*/);