pass()引用参数并将其传递给reference,但是实际上调用了一个rvalue参数reference(int&)而不是reference(int &&),这里是我的代码片段:
#include <iostream>
#include <utility>
void reference(int& v) {
std::cout << "lvalue" << std::endl;
}
void reference(int&& v) {
std::cout << "rvalue" << std::endl;
}
template <typename T>
void pass(T&& v) {
reference(v);
}
int main() {
std::cout << "rvalue pass:";
pass(1);
std::cout << "lvalue pass:";
int p = 1;
pass(p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
rvalue pass:lvalue
lvalue pass:lvalue
Run Code Online (Sandbox Code Playgroud)
因为p根据参考折叠规则很容易理解,但为什么模板函数传递v给reference()lvalue?
为什么模板函数传递
v给reference()左值?
那是因为v是一个左值.等等,什么?v是一个右值参考.重要的是它是一个参考,因此是一个左值.它只与rvalues绑定并不重要.
如果要保留值类别,则必须进行完美转发.完美转发意味着如果你传递一个rvalue(就像你的情况一样),函数将被调用rvalue(而不是左值):
template <typename T>
void pass(T&& v) {
reference(std::forward<T>(v)); //forward 'v' to 'reference'
}
Run Code Online (Sandbox Code Playgroud)
template <typename T>
void pass(T&& v) {
reference(v);
}
Run Code Online (Sandbox Code Playgroud)
你在这里使用转发引用非常好,但事实上现在有一个名称v,它被认为是lvalue一个右值引用.
简单地说,任何有名字的东西都是lvalue.这就是为什么需要Perfect Forwarding,以获得完整的语义,使用std::forward
template <typename T>
void pass(T&& v) {
reference(std::forward<T>(v));
}
Run Code Online (Sandbox Code Playgroud)
什么std::forward<T>只是做这样的事情
template <typename T>
void pass(T&& v) {
reference(static_cast<T&&>(v));
}
Run Code Online (Sandbox Code Playgroud)
看到这个 ;