We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
T&&在代码里并不总是右值引用:
T&&
void f(Widget&& param); // rvalue reference Widget&& var1 = Widget(); // rvalue reference auto&& var2 = var1; // not rvalue reference template<typename T> void f(std::vector<T>&& param); // rvalue reference template<typename T> void f(T&& param); // not rvalue reference
T&&代表两种含义:
万能引用一般出现在两个场景中:
template<typename T> void f(T&& param); // param is a universal reference
auto&& var2 = var1; // var2 is a universal reference
我们分别讨论下这两种场景。
我们注意到,涉及到万能引用的地方,都会有参数推导的过程,例如上面的T和var2. 而右值引用则没有这个过程:
void f(Widget&& param); // no type deduction; param is an rvalue reference Widget&& var1 = Widget(); // no type deduction; var1 is an rvalue reference
但是即使语句设计到参数推导,也不一定就是万能引用。例如:
template<typename T> void f(std::vector<T>&& param); // param is an rvalue reference std::vector<int> v; f(v); // error! can't bind lvalue to rvalue reference
这点还是比较好理解的。万能引用需要依靠表达式来初始化自己是右值引用还是左值引用,但是上面这个例子没有表现出这一点,它仅仅是推断了T的类型,但是param的类型一直都是std::vector<T>&&。
std::vector<T>&&
我们再举一个vector中的例子:
template<class T, class Allocator = allocator<T>> class vector { public: void push_back(T&& x); // rvalue reference template <class... Args> void emplace_back(Args&&... args); // universal reference };
push_back(T&& x)
std::vector<Widget> v; ... class vector<Widget, allocator<Widget>> { public: void push_back(Widget&& x); // rvalue reference … };
可以很明显的看出此时没有参数推导的过程。
template <class... Args> emplace_back(Args&&... args)
Args&&
有意思的是,当参数加上const后,就一定是右值引用:
template <class T> int f(T&& heisenreference); template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which would bind an rvalue reference to an lvalue
至于为什么会有这个规定,按照Why adding const makes the universal reference as rvalue的说法,大体有两点原因:
const
const T&&
template <typename T> void cref(const T&&) = delete;
对于auto的场景来说,所有的auto&&都是万能引用,因为它总是有参数推导的过程。例如定义一个记录函数执行时间的lambda(C++14中允许使用auto来声明lambda的函数):
auto&&
auto timeFuncInvocation = [](auto &&func, auto &&... params) { start timer; std::forward<decltype(func)>(func)( // invoke func std::forward<decltype(params)>(params)... // on params ); stop timer and record elapsed time; };
(完)
朋友们可以关注下我的公众号,获得最及时的更新:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
引子
T&&
在代码里并不总是右值引用:T&&
代表两种含义:如何区分
万能引用一般出现在两个场景中:
我们分别讨论下这两种场景。
模板参数
我们注意到,涉及到万能引用的地方,都会有参数推导的过程,例如上面的T和var2. 而右值引用则没有这个过程:
但是即使语句设计到参数推导,也不一定就是万能引用。例如:
这点还是比较好理解的。万能引用需要依靠表达式来初始化自己是右值引用还是左值引用,但是上面这个例子没有表现出这一点,它仅仅是推断了T的类型,但是param的类型一直都是
std::vector<T>&&
。我们再举一个vector中的例子:
push_back(T&& x)
中的T&&为右值引用,因为这个虽然是T&&,但是不涉及到参数推导。当push_back被instantiated时,实际的调用类似于:可以很明显的看出此时没有参数推导的过程。
template <class... Args> emplace_back(Args&&... args)
中的Args&&
为万能引用。Args与T是相互独立的,所以Args有一个独立的参数推断过程。const disqualify universal reference
有意思的是,当参数加上const后,就一定是右值引用:
至于为什么会有这个规定,按照Why adding
const
makes the universal reference as rvalue的说法,大体有两点原因:const T&&
允许你重载一个函数模板,它只接受右值引用。如果const T&&
也被当做universal reference,那么将没有办法让函数只接受右值引用。template <typename T> void cref(const T&&) = delete;
auto声明
对于auto的场景来说,所有的
auto&&
都是万能引用,因为它总是有参数推导的过程。例如定义一个记录函数执行时间的lambda(C++14中允许使用auto来声明lambda的函数):(完)
朋友们可以关注下我的公众号,获得最及时的更新:
The text was updated successfully, but these errors were encountered: