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

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

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

 

 

 
posted @ 2015-07-14 11:58  啦啦风吹  阅读(2176)  评论(0编辑  收藏  举报