为什么const double&&不适用于左值参考?

时间:2018-03-30 10:26:02

标签: c++ c++11 rvalue-reference rvalue lvalue

请解释一下,它是如何运作的? 为什么要加倍&&适用于左值和右值? 为什么const double&&不适用于左值?

template <typename U>
void function(U& var) {
    std::cout << var << std::endl;
}

int main()
{
    int var1 = 45;
    function(var1);
    function(45); //error
}

错误:从'int'函数(45)的rvalue初始化'int&amp;'类型的非const引用无效; ////////////////////////////////////////////////

template <typename U>
void function(const U& var) {
    std::cout << var << std::endl;
}

int main()
{
    int var1 = 45;
    function(var1);
    function(45);
}

/////////////////////////////////////////////// /

template <typename U>
void function(U&& var) {
    std::cout << var << std::endl;
}

int main()
{
    int var1 = 45;
    function(var1);
    function(45);
}

/////////////////////////////////////////////// /

template <typename U>
void function(const U&& var) {
    std::cout << var << std::endl;
}

int main()
{
    int var1 = 45;
    function(var1);  // error
    function(45);
}

错误:无法将'int'左值绑定到'const int&amp;&amp;'函数(var1);

3 个答案:

答案 0 :(得分:2)

double &&不适用于左值。但是,您的代码中没有double &&,对于推断的U &&,您有U。这是所谓的转发引用的特殊语法。

C ++模板推导规则中有一条特殊规则,即当参数类型为T&&时,其中T是推导类型,且参数是类型为{{1的左值'然后使用X代替X&进行类型推导。

在您的情况下,这意味着X被推断为U,因此参数int&的类型会从&#34; var&#34;进入int& &&

您可以通过搜索&#34;转发参考&#34;等条款来了解有关此机制的更多信息。 (历史上称为&#34;通用参考&#34;)或&#34;完美转发。&#34;

答案 1 :(得分:2)

我们首先总结一下规则。

  1. lvalues可以绑定到lvalue-reference
  2. 左值不能绑定到rvalue-reference
  3. rvalues可以绑定到lvalue-reference to const
  4. rvalues不能绑定到对非const
  5. 的左值引用
  6. rvalues可以绑定到rvalue-reference
  7. lvalues可以绑定到forwarding-reference(并保留其值类别)
  8. rvalues可以绑定到forwarding-reference(并保留其值类别)
  9. 第一种情况是对非const的左值引用,然后是

    function(var1); // rule#1 -> fine
    function(45);   // rule#4 -> fail
    

    第二种情况是lvalue-reference to const,then

    function(var1); // rule#1 -> fine
    function(45);   // rule#3 -> fine
    

    第三种情况是转发参考,然后是

    function(var1); // rule#6 -> fine
    function(45);   // rule#7 -> fine
    

    第四种情况是rvalue-reference,然后是

    function(var1); // rule#2 -> fail
    function(45);   // rule#5 -> fine
    

    值得注意的是rvalue-reference和forwarding-reference

    之间的区别

    (强调我的)

      

    函数模板的函数参数,声明为对同一函数模板的cv- 非限定类型模板参数的rvalue引用

答案 2 :(得分:0)

在您的示例中,function(var1)会将var1用法推断为lvalue。为了使其与基于rvalue的模板兼容,您必须帮助您的编译器:

template <typename U>
void function(const U&& var) {
    std::cout << var << std::endl;
}

int main()
{
    int var1 = 45;
    function(std::move(var1));  // let convert lvalue to rvalue
    function(45);
}

P.S。是的,你应该总是问自己“我真的需要那个左值参考,或者我对那个旧的左右参考完全没问题吗?”