zoukankan      html  css  js  c++  java
  • 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 变量的时候要注意这个问题。

  • 相关阅读:
    想起来好久没更新博客了
    操作系统文件管理
    PreparedStatement是如何大幅度提高性能的
    Java中快速排序的实现
    详解HashMap的内部工作原理
    关于Java集合的总结
    浅谈JVM内存区域划分
    解决java压缩图片透明背景变黑色的问题
    Vmware15.5中centos7minimal版 窗口字体太小
    字符长度还是字节长度
  • 原文地址:https://www.cnblogs.com/xiezhw3/p/3979317.html
Copyright © 2011-2022 走看看