为什么右值参考传递为左值参考?

时间:2016-08-20 02:33:39

标签: c++

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;
}

输出是:

rvalue pass:lvalue
lvalue pass:lvalue

对于p,根据参考折叠规则很容易理解,但为什么模板功能会将v传递给reference()作为左值?

2 个答案:

答案 0 :(得分:7)

  

为什么模板函数将v传递给reference()作为左值?

那是因为v是一个左值。等等,什么? v右值参考 。重要的是它是一个参考,因此是一个左值。它只与rvalues有关并不重要。

如果您想保留值类别,则必须执行完美转发。完美转发意味着如果你传递一个rvalue(就像你的情况一样),那么函数将被调用rvalue(而不是左值):

template <typename T>
void pass(T&& v) {
    reference(std::forward<T>(v)); //forward 'v' to 'reference'
}

答案 1 :(得分:7)

template <typename T>
void pass(T&& v) {
    reference(v);
}

您在这里使用转发引用非常好,但事实上现在有一个名称v,它被视为右值引用的lvalue

简而言之,任何名称都是lvalue。这就是为什么需要Perfect Forwarding来获得完整的语义,使用std::forward

template <typename T>
void pass(T&& v) {
    reference(std::forward<T>(v));
}

std::forward<T>做的只是做这样的事情

template <typename T>
void pass(T&& v) {
    reference(static_cast<T&&>(v));
}

this;