• C++中const声明数据时的编译器优化问题


    1、写在前面:

    int main(void) {
        const int a = 0;
        int* ptr = const_cast<int*>(&a);
    
        *ptr = 10;
    
        int b = a;
    
        int c = b;
    
        cout << a << endl;
        cout << b << endl;
        cout << *(&a) << endl;
        cout << *ptr << endl;
        cout <<  (&a == ptr) << endl;
    
    }
    

      对于以上代码,const声明了变量a为常量(伪常量),为什么叫伪常量呢?因为使用const_cast强制转换后,去掉其地址的const属性之后,使用ptr指针访问其地址并作修改,是合法的;真常量如p指向的内容为常量字符串,是不允许被修改的,但是同样的方法进行强制转换,编译不会报错,但是运行时,内核不会允许非法的写入操作,会抛出异常

    const char* p=“hello world”
    

      

    2、分析const声明的常量的的实际优化过程:

    对于这段代码,

     1 int main(void) {
     2     const int a = 0;
     3     int* ptr = const_cast<int*>(&a);
     4 
     5     *ptr = 10;
     6 
     7     int b = a;
     8 
     9     int c = b;
    10 
    11     cout << a << endl;
    12     cout << b << endl;
    13     cout << *(&a) << endl;
    14     cout << *ptr << endl;
    15     cout <<  (&a == ptr) << endl;
    16 
    17 }

    先看运行结果:

     这里可以看到,标识符a对应的内存的数据其实已经被ptr给改了,但是直接使用标志符a去赋值或者输出的时候,并没有以按地址取值的方式从内存空间去读相应的数据,因此我们可以猜想,必然是在某个环节作了替换操作

    2.1 看看这段代码预处理后的结果:并没有在预处理阶段作替换

    2.2 再看看这段代码对应的汇编代码呢?:(虽然汇编没学过,但是对比来看可以看出区别)就是在编译阶段完成了替换将标识符a直接替换成了一开始声明的数值,而不是去先读取对应的地址空间存放的值;

    3、总结

    从以上的分析过程可以看出,const声明的数据类型的优化是存在编译器中的,减少了一步取址操作,也就是说,只要你使用const声明了一个数据类型(这里只验证了内置数据类型),那么编译器就认定它不会被修改,因此在编译阶段就对它进行数值替换(因为实际上使用标识符a作为左值去对它进行重新赋值时,是不被允许的,编译时就会报错)。然而由于它的一开始声明时需要实际的内存空间去存放数据,但是块空间本质上又是可以读写的,只是因为const的属性在语法上作了限制而已,其实际地址空间是可以间接操作的,所以才被称为伪常量

    欢迎指正!转载请标明出处~   https://i.cnblogs.com/posts/edit;postId=15267210

  • 相关阅读:
    数据库日志文件很大,如何变小!
    导出到CSV文件乱码的问题
    JQuery 常用方法一览
    马云在阿里巴巴十周年晚会上的激情演讲
    jqueryeasyui(替代 extjs) 介绍
    写一个ajax程序就是如此简单
    ASP.NET 3.5之屠龙刀
    因并发而生,因云计算而热(专家聊天实录)
    专家访谈:为什么我们需要Erlang
    《写给大家看的设计书》封面评选结果揭晓
  • 原文地址:https://www.cnblogs.com/liwe1004/p/15267210.html
Copyright © 2020-2023  润新知