const 引用的分析

const 引用:

    在初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。尤其,允许为一个常量引用绑定非常量的对象、字面值,甚至是一个表达式。我们来看 const 引用的分析:

#include <iostream>
int main(int argc, char* argv[])
{
    const int &i = 12;
    return 0;
}

该代码的汇编代码如下:

int main(int argc, char* argv[])
{
00964C80  push        ebp  
00964C81  mov         ebp,esp  
00964C83  sub         esp,0D8h  
00964C89  push        ebx  
00964C8A  push        esi  
00964C8B  push        edi  
00964C8C  lea         edi,[ebp-0D8h]  
00964C92  mov         ecx,36h  
00964C97  mov         eax,0CCCCCCCCh  
00964C9C  rep stos    dword ptr es:[edi]  
    const int &i = 12;
00964C9E  mov         dword ptr [ebp-14h],0Ch  
00964CA5  lea         eax,[ebp-14h]  
00964CA8  mov         dword ptr [i],eax  

    return 0;
00964CAB  xor         eax,eax  
} 

我们可以看到,const 引用绑定一个12的时候,相当于有如下的步骤:

int temp = 12;

const int &i = temp;

我们上面分析过,引用实质上是一个指针,绑定一个对象就是保存对象的地址,那么一个12是没有地址的,所以需要一个临时变量。当然如果那个常量本身有地址,那么久直接将其地址保存到引用的内存空间。

下面考虑一个常量引用绑定到另一种类型时发生了什么:

int main(int argc, char* argv[])
{
    double num = 23.2;
    const int &i = num;

    return 0;
}

汇编结果:

    double num = 23.2;
000E436E  movsd       xmm0,mmword ptr ds:[0ECD80h]  
    double num = 23.2;
000E4376  movsd       mmword ptr [num],xmm0  
    const int &i = num;
000E437B  cvttsd2si   eax,mmword ptr [num]  
000E4380  mov         dword ptr [ebp-24h],eax  
000E4383  lea         ecx,[ebp-24h]  
000E4386  mov         dword ptr [i],ecx  

    return 0;
000E4389  xor         eax,eax  
}

 

我们可以看到,这里也是生成了一个临时变量,步骤相当于如下:

const int temp = num;

const int &i = temp;

 

所以,如果 i 不是常量引用,那么就应该允许对 i 所绑定的对象进行修改,但是 temp 是一个临时变量,明显是一个右值,不合法。

 

当然,如果是这样的代码

int main(int argc, char* argv[])
{
    const int num = 23;
    const int &i = num;

    return 0;
}

那么就不需要一个中间变量。

于是这里就出现了一个很有趣的问题,当一个 const 引用绑定一个非常量对象的时候,其行为可能是不同的,比如如下:

int main(int argc, char* argv[])
{
    double num = 23.9;
    const int &i = num;
    num = 54.9;
    cout << i << endl;

    return 0;
}

这份代码的结果是:23

而下面这份:

int main(int argc, char* argv[])
{
    int num = 23;
    const int &i = num;
    num = 54;
    cout << i << endl;

    return 0;
}

结果是 54. 就是因为上面那份生成了一个中间变量的原因。

所以在使用 const 引用绑定非 const 变量的时候要注意这个问题。

原文地址:https://www.cnblogs.com/xiezhw3/p/3979317.html