Sep 02, 2025
引用包装器
std::reference_wrapper 是 C++ 标准库 <functional> 头文件中的一个类模板,它的主要作用是将引用包装成一个可拷贝、可赋值的对象。
什么是 std::reference_wrapper?
在 C++ 中,引用(reference)本身不能被重新赋值,也不能作为容器的元素,因为它们不符合大多数标准库容器和算法对**可拷贝(Copyable)或可赋值(Assignable)**的要求。
std::reference_wrapper<T> 解决了这个问题。它内部持有一个 T 类型的引用,但它本身是一个对象,可以像普通对象一样被拷贝和赋值。当你拷贝一个 std::reference_wrapper 对象时,你拷贝的是对同一个原始对象的引用,而不是拷贝原始对象本身。
为什么需要它?
std::reference_wrapper 的主要用途是让引用能够与标准库容器和算法协同工作。
许多标准库组件,比如 std::vector、std::list、std::thread、std::sort 等,要求其操作的对象是可拷贝的。如果你直接尝试将引用放入这些容器或传递给这些函数,编译器会报错。
例如,下面的代码无法编译,因为 std::vector 不允许存储引用:
| 1 | // 错误示例:不能直接存储引用 | 
通过使用 std::reference_wrapper,你可以绕过这个限制,将引用“伪装”成一个可存储在容器中的对象:
| 1 | 
 | 
std::ref 和 std::cref 辅助函数:
为了方便使用,C++ 标准库提供了两个辅助函数:
- std::ref(T& obj):创建一个- std::reference_wrapper<T>对象。
- std::cref(const T& obj):创建一个- std::reference_wrapper<const T>对象,用于常量引用。
std::reference_wrapper 的常见用途
- 容器存储引用: 如上例所示,将引用放入 - std::vector、- std::map等容器中。
- 多线程传递可变对象: 当使用 - std::thread启动新线程时,如果你希望线程函数能够修改一个外部变量,你需要通过- std::ref传递引用。直接传递变量会发生拷贝。
- 泛型编程与算法: 在使用如 - std::bind或- std::sort等算法时,如果你想让它们操作原始对象而不是拷贝,- std::reference_wrapper是一个重要的工具。
例子:std::sort 的应用
假设你有一个自定义对象的向量,你想根据其中一个成员变量对它们进行排序,但你不想拷贝整个对象。你可以创建一个存储 std::reference_wrapper 的向量来对原始对象进行间接排序。
| 1 | 
 | 
总结:
std::reference_wrapper 是一种“引用对象”,它解决了 C++ 中引用不能被拷贝、不能被赋值、不能作为容器元素的问题。它的核心价值在于让引用能够无缝地融入 C++ 标准库的容器和算法生态系统,从而在需要传递引用而非拷贝时提供了强大的支持。