const_cast去除const限制,同一片内存
本质很简单,但一些优化 和 编程上的错误,却让人看不清本质。
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限制,同一片内存的更多相关文章
- 关于const和define的内存分配问题的总结
关于const和define的内存分配问题 const与#define宏定义的区别----C语言深度剖析 1, const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静 ...
- const 和 const_cast
对于const变量,我们不能修改它的值,这是这个限定符最直接的表现.但是我们就是想违背它的限定希望修改其内容怎么办呢?下边的代码显然是达不到目的的: ; int modifier = constant ...
- C++中四种类型转换以及const_cast是否能改变常量的问题
we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...
- C/C++(C++内存管理,内联函数,类型转换,命名空间,string类)
---恢复内容开始--- 内存管理 new/delete C语言中提供了 malloc 和 free 两个系统函数,#include "stdlib.h"库函数,完成对堆内存的申请 ...
- C++标准转换运算符const_cast
前面讲了C++继承并扩展C语言的传统类型转换方式,最后留下了一些关于指针和引用上的转换问题,没有做详细地讲述.C++相比于C是一门面向对象的语言,面向对象最大的特点之一就是具有“多态性(Polymor ...
- 【转】C++标准转换运算符const_cast
const_cast转换符是用来移除变量的const或volatile限定符. 对于const变量,我们不能修改它的值,这是这个限定符最直接的表现.但是我们就是想违背它的限定希望修改其内容怎么办呢? ...
- C++标准转换运算符
C++类型转换在实际编程中会经常使用,其实,本质上对象的类型用来解释(interpret)对象.因为,每个对象都占据一块内存空间,这块内存空间存放了一段二进制数据.通过标记该对象的类型,告诉如何看待这 ...
- C++Primer学习——类型转换
无符号之间的运算 当一个是无符号类型,另外一个是带符号类型: 如果无符号不小于带符号,那么带符号转换成无符号. 如果无符号小于带符号,当无符号类型的所有值都能存到带符号中时,则无符号转换成带符号,否则 ...
- c++ 中的符号与关键字
符号按照符号的ASC码数值从小到达排列,关键字按照英文字母排序. & [38] 位运算:取地址:左值引用[指针.引用都是可以做类型转换的] #include <iostream> ...
随机推荐
- Ubuntu 搭建 ***
在Ubuntu下安装ss很简单.只需要依次执行下面3条命令: apt-get update apt-get install python-pip pip install shadowsocks pip ...
- KDtree浅谈
KDtree浅谈 1.对KDtree的理解 首先要知道$KDtree$的用处,$KDtree$是用来进行多维数点的,一般这些点都是在在而二维及二维以上,因为一维上的问题,我们基本都可以运用线段树来解决 ...
- Xamarin XAML语言教程使用方法设置进度条进度
Xamarin XAML语言教程使用方法设置进度条进度 在ProgressBar中定义了一个ProgressTo方法,此方法也可以用来对进度条当前的进行进行设置,ProgressTo与Progress ...
- InputSplit—>RecordReder—>map(key,value,context)的过程解析
上图首先描述了在TaskTracker端Task(MapTask.ReduceTask)的执行过程,MapTask(org.apache.hadoop.mapred)首先被TaskRunner调用,然 ...
- IntelliJ debug grails 无效的解决办法
从Grails 2.2以后默认run-app命令将启动Grails应用程序在一个单独的Java虚拟机. 这就是所谓的分叉的Tomcat Grails中的执行. 这样的类路径Grails构建系统和应用程 ...
- Bluetooth篇 开发实例之八 匹配
自己写的App匹配蓝牙设备,不需要通过系统设置去连接. 匹配和通信是两回事. 用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK ...
- nodejs处理高并发问题
做了一个nodejs并发测试,先描述一下环境 数据库mysql,大概两张表,读取第一张表test的数据,拿出来-1,存到第二张testlog表记录一下,用jmeter同事模拟50个请求,结果发现, ...
- JAVA常见算法题(十八)
package com.xiaowu.demo; /** * 两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人,以抽签决定比赛名单. 有人向队员打听比赛的名单:a说他不和x比 ...
- numpy中结构数组
在c语言中,我们可以使用关键字struct定义结构类型.和c语言一样,numpy也可以创建结构定义,这样可以很方便的读取二进制的C语言结构数组,将其转换为numpy数组对象,假设我们定义的结构数组如下 ...
- bmp,jpg,png,tif,wmf,emf与eps图片格式转换
wmf/emf是两种Microsoft Windows的图形文件格式.它是一个矢量图格式,但是也允许包含位图.本质上,一个WMF文件保存一系列可以用来重建图片的Windows GDI命令.在某种程度上 ...