reference_wrapper
reference_wrapper是一个模板类
template <class T> class reference_wrapper;
用类型T实例化的reference_wrapper类能包装该类型的一个对象,并产生一个reference_wrapper< T >类型的对象,该对象就像是一个引用,与普通引用最大的不同是:该引用可以拷贝或赋值。
特点:没有默认构造函数,可以用一个想要引用的对象构造,或者用另一个reference_wrapper对象构造
int a = 10;
int b = 100;
reference_wrapper<int> r1 = a;
reference_wrapper<int> r2 = r1; 拷贝构造
r1 = 1; 错误,赋值运算符只接收同类型的对象
r1 = b; 正确,利用 b 构造一个临时对象,再用=运算符赋给 r1
r1 = r2; 正确
get函数
ref()返回的是一个reference_wrapper对象,并不是该对象的引用,所以如果要对返回对象调用成员函数就会报错。使用reference wrapper对象的get()方法,返回真正的引用(实际上reference wrapper是用指针表现出引用的所有特性,所以返回的应该是指针指向的对象)。
通过get成员获取到reference_wrapper所引用的对象,从而进行修改其值等操作。访问所引用的对象的话,直接访问reference_wrapper对象即可
int a = 10;
reference_wrapper<int> r1 = a;
cout << r1 << endl; // 10
cout << r1.get() << endl; // 10
r1.get() = 100;
cout << r1.get() << endl; // 100
特殊用法
可以存入容器中
普通的引用不是对象,所以无法存入任何标准库容器。reference_wrapper包装的引用就可以被存入容器中。
可以像普通的引用一样作为实参传入函数
一个reference_wrapper< T >类型的对象,可以作为实参,传入 形参类型为T的函数中
void func1(int value) { value = 100; } 不过 value 只是个拷贝,不是引用
void func2(int& value) { value = 1000; } 传入的是引用
int a = 10;
reference_wrapper<int> r = a;
func1(r); 传入的是 r 引用的值的 拷贝
cout << a << endl; 10
func2(r); 传入的是 r 引用的值的 引用
cout << a << endl; 1000
函数func的参数类型为int,而传递给func的参数确是reference_wrapper类型的对象。
- 若reference_wrapper包裹的引用是可以调用的,则reference_wrapper对象也是可调用的
- reference_wrapper 常通过引用传递对象给std::bind函数或者std::thread构造函数
- std::ref 和std::cref 通常用来产生一个reference_wrapper对象,ref()就是用reference_wrapper来包裹对象的一个简化写法。
auto r=ref(o);
//等价于
referencce_wrapper<dectype(o)> r(o);
示例
#include <functional>
using namespace std;
void func(int a, int b)
{
cout << "a = " << a <<",";
cout << "b = " << b << endl;
}
void func1(int i)
{
cout << "i = " << i << endl;
}
int main()
{
// 包裹函数指针
std::reference_wrapper<void(int,int)> f0 = func;
f0(5,7); // a = 5,b = 7
auto f1 = std::ref(func);
f1(5,7); // a = 5,b = 7
// 和bind结合使用
int i = 10;
auto f2 = std::bind(func1, i);
auto f3 = std::bind(func1, std::ref(i));
i = 30;
f2(); // i = 10
f3(); // i = 30
return 0;
}