"c++ 的 universal reference"
估计很多人都没有听说过 universal reference ,这个不奇怪,因为是 Scott
Meyers 自己创造的这个术语,参考
https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
。 C++ 标准里面没有这个术语,标准术语是 Reference collapsing
。但是
这种解释是更难理解,尽管更加准确。
Herb Sutter 同意这个东西应该有一个名字,但是应该叫做 forwarding reference。 因为 universal reference 似乎建议这个东西是更加通用的东西,到处都可以用,其实不是这样。 forwarding reference 则强调 这个东西只有在做 perfect forwarding 的时候才用。 关于 perfect forwarding ,看这里
我理解 scott meyers 的文章的意思只是指当看起来像右值引用的 T&&
出现在 template 的中,他就是
universal reference
,既不是 lvalue reference
也不是 rvalue reference
。
universal reference 的实际效果就是,你给他一个 lvalue reference 的时候,他就是 lvalue reference ,你给他 rvalue reference 的时候,他就是 rvalue reference 。
看下面的例子
#include <iostream>
#include <functional>
#include <boost/type_index.hpp>
using namespace std;
#define SHOW_TYPE_AND_SIZE(expr) if(1){ \
cout << #expr << ":\n"; show_type_and_size(expr); \
}while(0)
template<typename T>
void show_type_and_size(T&& x) {
cout << "T = "
<< boost::typeindex::type_id_with_cvr<T>().pretty_name() << ";\n"
<< boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name() << " x;\n"
<< "sizeof(x) " << sizeof(x) << "\n"
<< endl;
}
int foo() {
return 100;
}
int main(int argc, char *argv[])
{
int x = 100;
int&& rf = foo();
SHOW_TYPE_AND_SIZE(100);
SHOW_TYPE_AND_SIZE(rf);
SHOW_TYPE_AND_SIZE(foo());
SHOW_TYPE_AND_SIZE(x);
return 0;
}
输出如下:
100:
T = int;
int&& x;
sizeof(x) 4
rf:
T = int&;
int& x;
sizeof(x) 4
foo():
T = int;
int&& x;
sizeof(x) 4
x:
T = int&;
int& x;
sizeof(x) 4
这里需要注意,尽管 rf
的值是一个 rvalue reference ,但是他本身是一个 lvalue 。参考 C++11 的右值引用问题