【问题标题】:Why rvalue reference pass as lvalue reference?为什么右值引用作为左值引用传递?
【发布时间】:2016-08-20 02:33:38
【问题描述】:

pass() 引用参数并将其传递给reference,但是右值参数实际上称为reference(int&) 而不是reference(int &&),这是我的代码sn-p:

#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()

【问题讨论】:

    标签: c++


    【解决方案1】:
    template <typename T>
    void pass(T&& v) {
        reference(v);
    }
    

    您在这里使用转发引用很好,但事实上现在有一个名称v,它被认为是一个lvalue 到一个右值引用

    简单地说,任何有名字的东西都是lvalue。这就是为什么需要完美转发的原因,要获得完整的语义,请使用std::forward

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

    std::forward&lt;T&gt; 所做的只是做这样的事情

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

    this

    【讨论】:

      【解决方案2】:

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

      那是因为v 是一个左值。等等,什么? v 是一个右值引用。重要的是它是一个引用,因此是一个左值。只绑定右值也没关系。

      如果你想保留价值类别,你将不得不完美转发。完美转发意味着如果你传递一个右值(就像你的情况一样),函数将被一个右值(而不是左值)调用:

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

      【讨论】:

        猜你喜欢
        • 2017-05-15
        • 2020-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-08
        • 2017-04-15
        相关资源
        最近更新 更多