std::thread 构造必须传入可调用对象,空构造为未关联状态;析构前须 join() 或 detach(),否则 terminate();传参默认拷贝,引用用 std::ref,移动用 std::move;线程内异常需内部捕获。

std::thread 构造时必须传入可调用对象
直接写 std::thread t; 会编译失败,因为默认构造的 std::thread 是“未关联线程”的空状态,不能直接使用。你得立刻给它一个函数、lambda 或可调用对象。
- 最常见写法是传函数指针:
std::thread t(func, arg1, arg2); - 捕获局部变量的 lambda 也行:
std::thread t([&x, y]() { x += y; });(注意引用捕获需确保x生命周期足够长) - 成员函数要用
&Class::method+ 实例指针:std::thread t(&MyClass::run, &obj, 42);
忘记 join() 或 detach() 会导致程序崩溃
只要 std::thread 对象析构时仍处于“可加入(joinable)”状态,就会调用 std::terminate() —— 程序直接 abort,不抛异常,也不打印堆栈。
- 必须在析构前显式调用
t.join()(等待线程结束)或t.detach()(分离后由系统托管) - 推荐优先用
join(),除非你明确需要后台异步执行且不关心生命周期 - 容易漏掉的场景:函数提前 return、异常抛出、循环中重复创建未清理的 thread
传参默认按值拷贝,引用和移动语义要显式处理
std::thread 构造时对所有参数做完美转发,但底层实现会先拷贝一份 —— 这意味着你传 std::string 没问题,但传 int& 就可能绑定到临时拷贝上,导致意外行为。
- 要传引用,必须包一层
std::ref(x):std::thread t(func, std::ref(x)); - 要转移独占资源(比如
std::unique_ptr),必须用std::move(ptr) - 不要传局部变量的裸指针或引用,除非你能 100% 确保线程不会访问到已销毁的对象
线程函数里抛异常不会传播到主线程
std::thread 内部发生未捕获异常,会直接调用 std::terminate(),和析构时 joinable 一样暴力。
立即学习“C++免费学习笔记(深入)”;
- 必须在线程函数内部
try/catch,不能依赖外部捕获 - 如需传递错误信息,可用
std::promise/std::future或共享状态(如std::atomic<bool>+ 错误码) - 别指望
std::thread自带异常安全机制 —— 它的设计哲学就是“轻量、不隐藏开销”
std::thread 就能并行,关键在数据访问的边界是否清晰。


















