std::ref 是什么?
简单的一句话: std::ref 是一个包装器 ,用来告诉 std::thread(以及其他标准库函数如 std::bind):"请传递这个变量的引用(地址) ,而不是它的拷贝(副本)"。
为什么需要它?
std::thread 的构造函数在设计上非常谨慎。为了防止线程运行在分离模式(detach)下访问已经销毁的局部变量,它默认会把所有参数拷贝一份存到线程独立的存储空间里。
这就导致了一个问题:即使你在函数参数里写了 void func(int& n),
std::thread 依然会先拷贝一个副本,然后把这个副本的引用传给函数。
- 没有 std::ref:你修改的是副本,主线程里的原始变量不会变。
- 有 std::ref:你修改的是原始变量。
代码对比
#include <iostream>
#include <thread>
#include <functional> // std::ref 实际上在这里,但 <thread> 通常包含了它
void worker(int& n) {
n += 10;
}
int main() {
int n = 0;
// --- 错误示范 ---
// std::thread t1(worker, n);
// 编译可能会报错,或者虽然编译通过,但 n 仍然是 0。
// 因为 thread 内部机制拷贝了 n,试图把临时拷贝传给非 const 引用是非法的/无效的。
// --- 正确示范 ---
std::thread t2(worker, std::ref(n));
t2.join();
std::cout << "n is now: " << n << std::endl; // 输出 10
return 0;
}
底层原理: std::ref(n) 返回一个 std::reference_wrapper<int> 对象。这个对象是可以拷贝的,但它内部保存的是 n 的指针。当它被传递给线程函数时,它会"解包"回原始的引用。