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\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);

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

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

时间: 2024-11-10 15:26:21

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

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

关于const和define的内存分配问题 const与#define宏定义的区别----C语言深度剖析 1,  const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个拷贝. 2,  #define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值. 3,  #define宏没有类型,而const修饰的只读变量具有特定的类型. 总结:const节省了空间,避免了不必要的内存分配,同时提高了

[C/C++]用const_cast修改const变量会得到什么结果?

const int x=4; int& y = const_cast<int&>(x); ++y; 这时访问x,x会是多少呢? 根据C++11标准7.1.6.1.4: Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a constobject during its lifetime (3.8) results in undefined beh

【C/C++学院】0729-语音识别/Const关键字/字符串应用/内存分配以及处理海量数据

 语音识别 er.xml <?xml version="1.0" encoding="utf-8"?> <GRAMMAR LANGID="804"> <DEFINE> <ID NAME="CMD" VAL="10"/> </DEFINE> <RULE NAME="COMMAND" ID="CMD"

C++标准转换运算符const_cast

文章出处:http://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html 前面讲了C++继承并扩展C语言的传统类型转换方式,最后留下了一些关于指针和引用上的转换问题,没有做详细地讲述.C++相比于C是一门面向对象的语言,面向对象最大的特点之一就是具有“多态性(Polymorphism)”. 要想很好的使用多态性,就免不了要使用指针和引用,也免不了会碰到转换的问题,所以在这一篇,就把导师讲的以及在网上反复查阅了

Effictive C++知识点复习

1.尽量以const.enum.inline替换#define或者宁可以编译器替换预处理器eg:#define NUM_RATIO 1.653由于NUM_RATIO在编译器开始处理源码之前都被预处理器移走,因而当常量在编译时出错,只会提示到1.653.对于程序员并不知道1.653在哪个文件中存放.故追踪会浪费时间.即所使用的名称并未进入记号表中.解决方法:用一个常量替换上面的宏const double NumRatio = 1.653;注意:两个常量定义时的写法2.若在头文件定义一个常量的字符串

C++ 学习 lesson03

内联函数内联函数与带参数宏区别新的类型转换运算符const_cast<T>(expr)static_cast<T>(expr)reinterpret_cast<T>(expr) dynamic_cast<T>(expr) 当程序执行函数调用时,系统要建立栈空间,保护现场,传递参数以及控制程序执行的转移等等,这些工作需要系统时间和空间的开销.有些情况下,函数本身功能简单,代码很短,但使用频率却很高,程序频繁调用该函数所花费的时间却很多,从而使得程序执行效率降低

5个cast转型

const_cast 去除表达式的const性质 const_cast是唯一能将const性质转化掉的操作符,但执行其他任何类型的转换都会引起编译错误. 单纯的把常量转为变量是没多少意义的,也就是这种代码: 12 const int con =12;int cc= static_cast<int>(con); 直接用变量或者mutable就好了. 如果定义了一个非const的变量,却使用了一个指向const值的指针来指向它(不规范的风格),在进程的某处我们想改变这个变量的值了,但手头只持有指针

Effective C++ 条款3 尽可能用const

1. const可被施加于任何作用域内的对象,函数参数,函数返回类型,成员函数本体.用const修饰指针,如果const出现在*之前,表明指针不能更改所指向的对象的内容,如果const出现在*之后,表明指针只能指向同一块内存.另外int const*p和const int*p含义相同.如果对象成员有普通指针,那么构造该类的一个const对象时,const修饰使得该指针只能指向同一块内存,但指针指向的内容可以改变. 2. 将某些东西声明为const可以帮助编译器侦测出错误用法. 3. 编译器强制实

C++中const关键字详解

1.什么是const? const意味着是常量类型,被const修饰的变量或对象是不能被修改和更新的,当然在某些情况下,我们可以偷梁换柱的改变它. 2.为什么要引入const? 最初的目的是为了取代预编译指令:define  MAX  (1024)  ,显然这样的宏定义常量是C语言中继承而来的,C++意识到这种宏替换会存在边际效应,因此希望const能替代它 3.const有什么作用? (1)可以定义const常量,具有不可变性. 例如: const int Max=100; int Array