将shared_ptr传递给线程函数时如何避免clang-tidy警告?

问题描述 投票:0回答:1

我的 C++ 代码看起来(简化)如下:

#include <unistd.h>

#include <iostream>
#include <memory>
#include <string>
#include <thread>

std::thread the_thread;

void my_thread_func(const std::shared_ptr<std::string>& string_ptr) {
    std::cout << "at thread begin: " << *string_ptr << std::endl;
    sleep(1);
    std::cout << "at thread finish: " << *string_ptr << std::endl;
}

void start_thread() {
    auto local_string_ptr = std::make_shared<std::string>("foobar");
    the_thread = std::thread(&my_thread_func, local_string_ptr);
}

int main(int, char**) {
    start_thread();
    sleep(2);
    the_thread.join();
}

(在编译器资源管理器上:https://godbolt.org/z/9GYTf7orz

当我运行此代码时

clang-tidy --checks=performance-unnecessary-value-param
时,它会发出警告:

<source>:10:50: warning: the parameter 'string_ptr' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
   10 | void my_thread_func(std::shared_ptr<std::string> string_ptr) {

但我的理解是,将

string_ptr
作为 const 引用传递给
my_thread_func()
是不正确的,因为这样线程将拥有对
start_thread()
本地对象的引用,并且该对象在线程运行时被销毁。

我的问题:

  • 使用
    void my_thread_func(const std::shared_ptr<std::string>& string_ptr)
    是否正确(且推荐),还是会出现错误?
  • clang-tidy 警告是正确的还是误报?
  • 我的代码通常不正确/不优雅,从而首先导致这个问题吗? IE。写这个的最好方法是什么?

我的经验是 clang-tidy 通常是正确的:-) 这就是为什么我对这里的警告感到困惑。

c++ multithreading warnings clang-tidy pass-by-const-reference
1个回答
1
投票

clang-tidy 警告假设一个单线程上下文:对函数的普通调用

int get(std::shared_ptr<int> p,std::binary_semaphore &s) {
  s.acquire();
  return *p;
}

可能非常需要

std::shared_ptr
参数(对象,而不是引用)来保持
int
存活足够长的时间以返回它。 (调用者可能从某个表中获取了对
std::shared_ptr
的引用,而不是为调用构建它,并且无论信号量发出什么信号,都可能在执行此操作后立即删除唯一的其他引用。)

另外,即使为线程调用的函数具有引用 parameter,它也不会是对

std::thread
构造函数的参数的引用:每个这样的参数都被复制到一个临时 T 中,其生命周期为线程,参考文献是T。 (正如评论中提到的,您可以使用
std::ref
生成
std::reference_wrapper
,它可以转换回对原始参数的引用。)这意味着您可能根本不需要
std::shared_ptr
:您可以只构造对象作为参数,它将被移动到T

© www.soinside.com 2019 - 2024. All rights reserved.