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

  • 相关阅读:
    2016/3/28 大三下第一月
    hihoCoder1284机会渺茫(唯一分解定理 + 约分)
    瞬沐队小组会议
    本周编程
    团队简介及团队课题
    本周编程
    Python环境的配置
    疫情图表
    本周编程
    返回一个数组中和最大的子数组
  • 原文地址:https://www.cnblogs.com/xiezhw3/p/3979317.html
Copyright © 2020-2023  润新知