为什么在显式更改int的值时,对const int(绑定到int)的引用值会发生变化?

时间:2017-12-10 06:28:52

标签: c++

我期望会发生的是,因为参考类型和我不匹配我必须已经转换为临时然后分配给r2但是当我改变时我明确地改为53 r2也改变了

int i = 42; 
const int &r2 = i; 

i = 53;
std::cout << r2<<"\n";

return 0;

使用双

时不会发生同样的情况
double i = 42.4; 
const int &r2 = i; 

i = 53.7;
std::cout << r2<<"\n";

return 0;

此处打印的值与预期值相同42

4 个答案:

答案 0 :(得分:3)

语言规则明确声明如果引用的类型与lvalue初始化程序的类型引用兼容,则引用将直接绑定到初始化程序。见8.6.3 / 5

  

5 类型“cv1 T1”的引用由“cv2 T2”类型的表达式初始化,如下所示:
   - 如果引用是左值引用和初始化表达式
   - 是左值(但不是位域),“cv1 T1”与“cv2 T2”引用兼容,
  [...]
  然后引用绑定到初始化表达式lvalue。

参考兼容性允许参考类型中的额外cv资格。因此,尽管您的引用类型中有额外的const,但语言仍然需要将其直接绑定到i。换句话说,在您的第一个示例中,实际执行匹配的类型。

在您的第二个示例中,类型非常不同,彼此不是参考兼容的。没有直接绑定引用。

答案 1 :(得分:1)

您手上有两种不同的情况。这里

int i = 42; 
const int &r2 = i;

你有一个对象。和一个相同类型的const引用。 r2可能会直接与i绑定。您不能使用r2修改i,但i本身不是常量。您基本上创建了对象的const视图。

这是设计的,当你想到它时,非常有用。假设我们要打印一百万个std::vector个对象。我们的函数应该传递一个引用,最好不要修改向量。所以通过&#34; const view&#34;矢量正是我们所需要的。

在另一种情况下,您有一种类型的对象,以及对完全不相关类型的引用。引用不能直接绑定,所以我们确实为它创建了一个临时的int来绑定。临时和原始对象是分开的。正如你所观察到的那样。

答案 2 :(得分:0)

在双重的情况下,你绑定一个const int引用,所以在这种情况下需要临时(转换),在第一种情况下,你说这个值不能通过引用更改但没有任何阻止原来被改变了。

考虑像const volatile int&amp; amp;我= ...;在那里你明确地告诉编译器我可能因为编译器无法推断而改变。

答案 3 :(得分:0)

在分配给不同类型的引用之前,会发生类型转换,并且值将存储在不同的位置,引用将指向该位置。如果它的类型不同,r2将不会指向i。在你的情况下,cvttsd2si将被调用,double值将被转换为有符号的双字整数。 检查为下面的代码版本生成的汇编代码。

对于不同类型

 #double i = 42 ;
 movsd   .LC0(%rip), %xmm0   #, tmp90
 movsd   %xmm0, -8(%rbp) # tmp90, i
 # *.cpp:6:     const int &r2 = i; 
 movsd   -8(%rbp), %xmm0 # i, tmp91
 cvttsd2si   %xmm0, %eax # tmp91, _2
 movl    %eax, -20(%rbp) # _2, D.39824
 leaq    -20(%rbp), %rax #, tmp92
 movq    %rax, -16(%rbp) # tmp92, r2

当变量和引用是相同类型时。

# *.cpp:5:     int i = 42;           
movl    $42, -12(%rbp)  #, i       
# *.cpp:6:     const int &r2 = i; 
leaq    -12(%rbp), %rax #, tmp89
movq    %rax, -8(%rbp)  # tmp89, r2