首页 > 代码库 > const 引用的分析

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 变量的时候要注意这个问题。

const 引用的分析