1. std::ref
为什么需要
std::ref
?
在以下场景中,参数默认按值传递,若想传递引用,需用std::ref
:
- 模板函数或泛型代码:类型推导可能无法直接处理引用。
- 多线程:
std::thread
构造函数默认按值传递参数。 - 函数对象:如
std::bind
、std::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
的核心行为
- 生成引用包装器:
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;
}