为什么const double引用可以分配给int而不是非const引用?

时间:2016-05-28 00:46:11

标签: c++ reference const

最近我编写了一个函数,它正在对双数进行一些处理,但是由于一些变化,我需要对整数进行相同的处理,所以用下面给出的更简单的例子简化长篇故事:

void display(double& arg)
{
    std::cout << arg << std::endl;
}
int main()
{
    int inum = 10;
    display(inum);
    return 0;
}

我发现上面的代码没有编译并且给出错误“类型的引用”double&amp;“(不是const-qualified)不能用类型”int“的值初始化,因为错误非常直观所以我修改了代码并将显示函数的参数更改为const double&amp; arg,一切似乎都正常工作。所以我的问题是

“const double&amp;”中究竟发生了什么?案件?需要完整的解释吗?

现在,在阅读了所提供的一些解释和问题链接后,我明白转换产生的rvalue和rvalue不能绑定到临时值,所以我寻找的唯一推理是为什么转换产生rvalue?

3 个答案:

答案 0 :(得分:3)

以下是我看到的错误示例:error: invalid initialization of non-const reference of type 'double&' from an rvalue of type 'double'

显然抱怨double&(这是display函数的参数类型)无法使用类型为double的右值进行初始化。好吧,inum被传递给函数,但它的类型是int。但是,int可以隐式转换为double,这种情况正在发生。转换产生rvalue(即临时)double ,但暂时不能绑定到非const引用

将其更改为void display(const double& arg)是有效的,因为一切都与上面说明的相同。但是,右值可以绑定到 const 引用

我没有官方标准,但以下引用来自n4296 draft

  

4次标准转化[转化]

     

1 标准转化是具有内置含义的隐式转化。第4条列举了全套这类   转换。标准转换序列是按以下顺序的一系列标准转换:

     

(1.1) - 来自以下集合的零或一次转换:左值到右值的转换,数组到指针的转换以及函数到指针的转换。

     

3 当且仅当声明T t = e时,表达式e可以隐式转换为类型T.形式良好,   对于一些发明的临时变量t(8.5)。

     

6 任何隐式转换的效果与执行相应的声明和初始化相同   然后使用临时变量作为转换结果。

答案 1 :(得分:1)

System.out.println是对double的引用,它存在于其他地方。通常,您可以使用它来修改调用者提供的变量。但是,如果来电者提供了double&的地址,并且您尝试将其视为int,那么事情将会非常糟糕!编译器还禁止像double一样调用像void bar(double&)这样的函数,因为尝试修改临时值通常没有意义。

另一方面,使用bar(3.14),您保证不会更改值:您只是通过引用来获取它以避免复制,而不是修改它。因此,可以使用临时调用const double&,如void foo(const double&):编译器传递临时地址,foo(3.14)取消引用它以获取值,并在{{1}之后返回临时消失。

这就是这里发生的事情:当签名要求foo,并且你提供foo时,会创建一个临时双精度(从const double&投射),其地址被传递到int

答案 2 :(得分:1)

  • 如果inumdouble,您的代码就会生效,因为您的参数是lvalue(您可以使用其地址)。

  • 如果您的函数签名为void display(const double& arg),那么它将起作用,因为提升的参数是临时的,您可以将const引用绑定到临时的将其生命周期延长到const reference标识符的范围。

  • 如果您的函数签名为void display(double&& arg),那么它将起作用,因为提升的参数是临时的,您可以将rvalue引用绑定到临时的将其生命周期延长到rvalue reference标识符的范围。

  • 上述两种方法之间的区别在于,您可以修改后者中的arg及其C ++ 11及以上版本....

在C ++中,您不能将非const引用(特别是左值)绑定到临时引用。

会发生int doublevoid inc(double& x) { x += 0.1; } int i = 0; inc(i);

引用implicit conversion

  

不允许引用临时工具的原始案例是   功能参数。假设这是允许的:

options
     

为什么我没有改变?