std::thread构造时参数被拷贝或移动到线程内部,安全可靠;普通函数按值传参,引用需std::ref;lambda推荐按值捕获;成员函数首参为对象指针或引用;避免悬垂引用。
创建线程时,可将函数对象和参数一并传给 std::thread 构造函数。参数会被**拷贝(或移动)进线程内部存储**,与主线程栈无关,安全可靠。
[=])或显式移动捕获([x = std::move(x)]),避免悬垂引用&obj 或 std::ref(obj)),后续才是成员函数的实参示例:
void foo(int x, const std::string& s) { /* ... */ }
class A { public: void bar(double d) {} };
int main() {
std::string s = "hello";
A a;
// 按值传参(s 被拷贝)
std::thread t1(foo, 42, s);
// 传引用需 std::ref
std::thread t2(foo, 42, std::ref(s));
// 调用成员函数
std::thread t3(&A::bar, &a, 3.14);
t1.join(); t2.join(); t3.join();
}
lambda 是封装参数最自然的方式,尤其适合需要访问局部变量、或参数类型复杂/不可拷贝的场景。
[=]:所有自动变量被拷贝进 lambda 闭包,线程内安全使用[&]:危险!若线程生命周期超过变量作用域,会引发未定义行为[x = std::move(x), &y],精确控制每个变量的传递方式示例:
std::vectordata = {1,2,3}; // 安全:data 被拷贝进闭包 std::thread t([data]{ for (int x : data) std::cout << x << " "; }); t.join(); // 危险!data 可能已析构 // std::thread t2([&data]{ ... }); // ❌ 不要这样写
std::bind 可提前绑定部分或全部参数,生成可调用对象,再传给 std::thread。本质是函数对象适配,语义清晰但略显冗余。
_1, _2... 用于预留运行时传入的参数示例:
void log(const char* tag, int val, const std::string& msg) {
std::cout << tag << ": " << val << " - " << msg << "\n";
}
std::string msg = "done";
// 绑定前两个参数,第三个留空
auto bound = std::b

ind(log, "INFO", 100, std::placeholders::_1);
std::thread t(bound, msg); // 运行时传 msg
t.join();参数传递看着简单,但几个关键点容易出错:
std::thread(f, std::ref(x)),否则传的是 x 的拷贝std::move(ptr),否则编译失败std::forward(args)...,日常开发无需手动实现一句话总结:优先用构造函数传值 + std::ref 处理引用,lambda 捕获按需选择 [=],避开栈变量引用,就基本不会踩坑。