• const_cast去除const限制,同一片内存


    本质很简单,但一些优化 和 编程上的错误,却让人看不清本质。

    :const_cast<type_id> (expression)
    该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
    一、常量指针被转化成非常量的指针,并且仍然指向原来的对象
    二、常量引用被转换成非常量的引用,并且仍然指向原来的对象; 
      
     就是说,转换之后仍是原来的内存,只是变量的属性变了,看待该内存的方式变了。
    下面解释一下,一些让人看不清本质的情况
     
    1.编译器的优化
      
    const int a = 10;
    cout<<a<<endl;   //10
    	
    //a = 20;   //编译出错
    const_cast<int&>(a) = 20; //转化成引用
    cout<<"a: "<<a  <<endl;  //a的结果依然是10,a的内容没有变化?
    

        可以看到a的值没有变化,依然是10。为什么呢?难道是新的内存,修改的是临时值? 但引用应该只是别名。  

    转换成指针看看地址

    //int * p = &a;  //编译出错
    int * p = const_cast<int*>(&a);
    *p = 20;
    cout<<"a: "<<a << "  a address:"<< &a <<endl;   //10
    cout<<"*p:"<<*p<<"  p content:"  <<p<< " p address: "<<&p<<endl;  //20
    	//但p指向的是a的地址,两个内容应该 一致,所以是由于编译器的优化。
    

      看到a的值没变,但*p变化了。而&a 与p 的内容一样,即p就是指向a的,两个是同一片内存,但打印出来的内容不一致,考虑由于编译器优化的原因。

    volatile const int b=11;
    cout<<"b:"<<b<<endl;
    const_cast<int&>(b) = 22;
    cout<<"b: "<<b << "  b address:"<< &b <<endl;  //22好了,引出新问题,为什么地址为1
    printf("printf:%p
    ",&b);  //可以打印出地址
    

      好了,加上volatile之后,不让编译器优化,每次都去内存中取值就正确了。

        所以const_cast转化成引用或指针后,扔指向的是原来的内存,可以修改内存中的数据。

       注:这里有一个新的发现,打印&b, b的地址的时候,用cout打印出1,printf打印出地址。这是为什么呢?仍是编译器的优化吗?

    2.一些错误导致本质不清。

      

    volatile const int b=11;
    int bk = const_cast<int&>(b);
    bk = 22;
    cout<<"b: "<<b << " bk:  "<< bk <<endl;  
    //  b: 11  bk:22
    	
    

      仔细看,可以知道,修改的是变量bk的值,并没有修改b所只内存的值。虽然是引用,但bk没有申明为引用,是个新的变量。

    可能本意是 int& bk = const_cast<int&>(b);

      因此,很多错误,导致原本看清的本质变得模糊,甚至开始怀疑。

     在测试的时候,必须保证你的代码是你原本想要的样子,才能继续测试你怀疑的真相!

     
    路是一步一步走的
  • 相关阅读:
    更改Delphi系统的默认字体
    Delphi TThread中文注释
    Delphi中的线程类 TThread详解
    TreeView使用笔记
    用未公开函数实现Shell操作监视
    Delphi面向对象编程的20条规则
    Delphi操作Excel命令
    delphi 创建一个纯文本文件
    判断滚动条到底部、
    数据库性能优化之SQL语句优化1
  • 原文地址:https://www.cnblogs.com/Lalafengchui/p/4645068.html
Copyright © 2020-2023  润新知