int i, j;
auto r = std::ref(i); // r refers to i
r = std::ref(j); // Okay; r refers to j
r = std::cref(j); // Error: Cannot bind reference_wrapper<int> to <const int>
int i;
auto t1 = std::make_tuple(i); // Copies i. Type of t1 is tuple<int>
auto t2 = std::make_tuple(std::ref(i)); // Saves a reference to i.
// Type of t2 is tuple<int&>
vector<int*> a; // the int values might or might not be owned
vector<unique_ptr<int>> b; // the int values are definitely owned
vector<reference_wrapper<int>> c; // the int values are definitely not owned
68
您可以将其视为引用的便利包装器,以便您可以在容器中使用它们 .
std::vector<std::reference_wrapper<T>> vec; // OK - does what you want
std::vector<T&> vec2; // Nope! Will not compile
4 回答
std::reference_wrapper
与模板结合使用非常有用 . 它通过存储指向它的指针来包装对象,允许重新分配和复制,同时模仿其通常的语义 . 它还指示某些库模板存储引用而不是对象 .考虑STL中复制仿函数的算法:您可以通过简单地传递引用包装器而不是仿函数本身来避免该副本:
这是因为......
reference_wrapper
s overload operator()因此可以像调用它们的函数对象一样调用它们:reference_wrappers
只是指定了指针 .复制引用包装器实际上相当于复制指针,这种指针虽然便宜 . 使用它时固有的所有函数调用(例如
operator()
的函数调用)应该只是内联,因为它们是单行的 .reference_wrapper
是通过std::ref and std::cref创建的:template参数指定所引用对象的类型和cv限定条件;
r2
指的是const int
,只会产生对const int
的引用 . 调用带有const
仿函数的包装器只会调用const
成员函数operator()
.Rvalue初始化程序是不允许的,因为允许它们弊大于利 . 因为rvalues无论如何都会移动(并且guaranteed copy elision甚至's avoided partly), we don' t改进了语义;我们可以引入悬空指针,因为参考包装器不会延长指针的生命周期 .
图书馆互动
如前所述,通过将相应的参数传递给
reference_wrapper
,可以指示make_tuple
在结果tuple
中存储引用:请注意,这与
forward_as_tuple
略有不同:此处,不允许使用rvalues作为参数 .std::bind显示相同的行为:它不会复制参数,但如果它是
reference_wrapper
则存储引用 . 如果在使用bind
-functor时不需要复制该参数(或仿函数!)但保持在范围内,则非常有用 .与普通指针的区别
reference_wrapper
具有隐式conversion operator,可以像它们包装的对象一样被调用 .与指针不同,
reference_wrapper
s没有空状态 . 它们必须用either a reference or another reference_wrapper进行初始化 .reference_wrapper
可以重新分配 .至少有两个激励目的
std::reference_wrapper<T>
:std::for_each()
的大型函数对象,它按值获取其函数对象参数 . 为避免复制对象,您可以使用将参数作为
std::reference_wrapper<T>
传递给std::bind()
表达式通过引用而不是值来绑定参数是很常见的 .std::reference_wrapper<T>
与std::make_tuple()
一起使用时,相应的元组元素变为T&
而不是T
:就自我记录代码而言,另一个区别是使用
reference_wrapper
本质上否定了对象的所有权 . 相反,unique_ptr
断言所有权,而裸指针可能拥有或不拥有(如果不查看大量相关代码,则无法知道):您可以将其视为引用的便利包装器,以便您可以在容器中使用它们 .
它基本上是
CopyAssignable
的CopyAssignable
版本 . 任何时候你想要一个引用,但它必须是可分配的,使用std::reference_wrapper<T>
或其辅助函数std::ref()
. 或者使用指针 .其他怪癖:
sizeof
:比较: