1. std::ref

为什么需要 std::ref
在以下场景中,参数默认按值传递,若想传递引用,需用 std::ref

  • 模板函数或泛型代码:类型推导可能无法直接处理引用。
  • 多线程:std::thread 构造函数默认按值传递参数。
  • 函数对象:如 std::bindstd::function 等。

示例:多线程中传递引用

#include <thread> #include <functional> void modify(int& x) { x = 42; } int main() { int value = 0; // 错误!线程默认按值传递参数,无法绑定到非 const 引用 // std::thread t(modify, value); // 正确:使用 std::ref 传递引用 std::thread t(modify, std::ref(value)); t.join(); std::cout << value; // 输出 42 return 0; }

std::ref 的核心行为

  1. 生成引用包装器:std::ref(obj) 返回一个 std::reference_wrapper 对象。
  • 支持拷贝:引用包装器可被拷贝,原始对象的引用关系保持不变。
  • 隐式转换:std::reference_wrapper 可隐式转换为 T&
    示例:在泛型函数中使用
#include <functional> template<typename T> void process(T arg) { arg.get() = 100; // 通过 get() 获取原始引用 } int main() { int x = 0; process(std::ref(x)); // 传递引用包装器 std::cout << x; // 输出 100 return 0; }

2. std::cref:不可修改的引用包装器

std::cref(obj) 生成 const 引用包装器,用于只读场景。
类似 const T&,但支持拷贝和传递。

示例:

#include <functional> #include <iostream> void print(const int& x) { std::cout << x; } int main() { int value = 10; auto func = std::bind(print, std::cref(value)); func(); // 输出 10 return 0; }