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

: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\n",&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);

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

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

 

const_cast去除const限制,同一片内存的更多相关文章

  1. 关于const和define的内存分配问题的总结

    关于const和define的内存分配问题 const与#define宏定义的区别----C语言深度剖析 1,  const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静 ...

  2. const 和 const_cast

    对于const变量,我们不能修改它的值,这是这个限定符最直接的表现.但是我们就是想违背它的限定希望修改其内容怎么办呢?下边的代码显然是达不到目的的: ; int modifier = constant ...

  3. C++中四种类型转换以及const_cast是否能改变常量的问题

    we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...

  4. C/C++(C++内存管理,内联函数,类型转换,命名空间,string类)

    ---恢复内容开始--- 内存管理 new/delete C语言中提供了 malloc 和 free 两个系统函数,#include "stdlib.h"库函数,完成对堆内存的申请 ...

  5. C++标准转换运算符const_cast

    前面讲了C++继承并扩展C语言的传统类型转换方式,最后留下了一些关于指针和引用上的转换问题,没有做详细地讲述.C++相比于C是一门面向对象的语言,面向对象最大的特点之一就是具有“多态性(Polymor ...

  6. 【转】C++标准转换运算符const_cast

    const_cast转换符是用来移除变量的const或volatile限定符. 对于const变量,我们不能修改它的值,这是这个限定符最直接的表现.但是我们就是想违背它的限定希望修改其内容怎么办呢? ...

  7. C++标准转换运算符

    C++类型转换在实际编程中会经常使用,其实,本质上对象的类型用来解释(interpret)对象.因为,每个对象都占据一块内存空间,这块内存空间存放了一段二进制数据.通过标记该对象的类型,告诉如何看待这 ...

  8. C++Primer学习——类型转换

    无符号之间的运算 当一个是无符号类型,另外一个是带符号类型: 如果无符号不小于带符号,那么带符号转换成无符号. 如果无符号小于带符号,当无符号类型的所有值都能存到带符号中时,则无符号转换成带符号,否则 ...

  9. c++ 中的符号与关键字

    符号按照符号的ASC码数值从小到达排列,关键字按照英文字母排序. & [38] 位运算:取地址:左值引用[指针.引用都是可以做类型转换的] #include <iostream> ...

随机推荐

  1. 跨集群拷贝hdfs

    拷贝 A集群的test目录到B集群的test目录 问题1: cause:java.io.IOException: Failed to run job : User root cannot submit ...

  2. 用SparkSQL构建用户画像

    用SparkSQL构建用户画像 二.  前言 大数据时代已经到来,企业迫切希望从已经积累的数据中分析出有价值的东西,而用户行为的分析尤为重要. 利用大数据来分析用户的行为与消费习惯,可以预测商品的发展 ...

  3. Burnside引理与polay定理

    #Burnside引理与polay定理 引入概念 1.置换 简单来说就是最元素进行重排列 是所有元素的异议映射,即\([1,n]\)映射到\([1,n]\) \[ \begin{pmatrix} 1& ...

  4. POJ 2549:Subsets(哈希表)

    [题目链接] http://poj.org/problem?id=2549 [题目大意] 给出一个数集,从中选择四个元素,使得a+b+c=d,最小化d [题解] 我们对a+b建立Hash_table, ...

  5. Java多线程设计模式(2)生产者与消费者模式

    1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...

  6. iOS禁止多点操作(按钮和Table项)

    1)避免同时点击多个按钮: [btn setExclusiveTouch:YES]; 设置确保当btn点击时,其他按钮不响应: (2)避免同时点击UITableView中多个row -(NSIndex ...

  7. Java杂谈1——虚拟机内存管理与对象访问

    1.理解JAVA虚拟机的内存管理 运行时的数据区 从java虚拟机的内存分配来看,一个java程序运行时包含了如下几个数据区: a)     程序计数寄存器(Program Counter Regis ...

  8. Ubuntu 16.04服务器版查看DHCP自动分配的IP、网关、DNS

    说明: 1.在服务器版本中,没有想桌面版一样的NetworkManager工具,所以的一切都是在命令行上操作的. 2.本文只针对DHCP默认分配的IP进行查看. 方法: 1.如果要使用DHCP,那么需 ...

  9. red-lang

    Red is a next-generation programming language strongly inspired by Rebol, but with a broader field o ...

  10. 鼠标悬浮tip 显示

    鼠标悬浮tip 显示 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...