关于const_cast问题?
请问,ncref和val的地址一样,使用ncref指针修改值之后为什么val值不变? const_cast<typename> 运算符,只是改变指针的const属性,但const命名的变量依旧不能改变。换句话说,就是指针不是const指针,const int* 变为int*,但指向的变量val依旧是const。
我觉得是编译器行为,目的是保证只要const的变量,就一定不能改变,至于上面的运算符的作用,往往是用于参数传递。
如有函数 void fun(int n);
如果需要传入的实参是一个const变量,而我们也知道fun函数本身并不会改变参数的值,这个时候,如果把形参声明为非const是无法通过编译的,只有用const_cast<int>,之后,可以代入函数。
反汇编的源码也说明了const值的不可改变,你的程序,用vs2010调试运行时,cout<<val的反汇编代码,
00F942DCpush 0Dh
00F942DEmov ecx,dword ptr
你看这里压入的是 0Dh,也就是13这个字面变量,
而普通的变量打印的汇编代码则是
00F9428Cpush eax
00F9428Dmov ecx,dword ptr
00F94293call dword ptr
压入的是eax(或别的寄存器),寄存器里存着变量的值,也显示出是一个普通变量。
看的出来,该地址的值虽然被改变了,但val依旧被解释为字面常量,并且在编译过程中已经被替换为13了,也正因为编译时就是13,所以编译器是不允许你改变val的值的,否则就乱套了。
但也有一个很有意思的事情,*(&val)的值虽然为13不变,但*(int*)(&val)的值却为23.这里的强制类型转换,应该彻底抹去了指针和val变量的关系。看汇编代码,也是体现出前者是字面值,而后者是一个变量。
cout<<"*(&val): "<<*(&val)<<" ;*(int*)(&val): "<<*(int*)(&val)<<endl; //13 ;23
00F94318mov esi,esp
00F9431Amov eax,dword ptr
00F9431Fpush eax
00F94320mov edi,esp
00F94322mov ecx,dword ptr //对应源代码 *(int*)(&val)
00F94325push ecx //压入的是寄存器
00F94326push offset string " \xa3\xbb*(int*)(&val): " (0F97AFCh)
00F9432Bmov ebx,esp
00F9432Dpush 0Dh //对应源代码 *(&val),压入的是字面常量0Dh
00F9432Fpush offset string "*(&val): " (0F97898h)
00F94334mov edx,dword ptr
在你的程序基础上我增加了若干代码,我觉得基本上说明了const_cast<typename>运算符的这种性质
#include "stdafx.h"
#include<iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
const int val=13;
int temp=15;
const int* ptr=&temp;
int* ppp=const_cast<int*>(ptr);
*ppp=16;
// (*ptr)++; // 接触引用的值依旧是const
ptr++; //说明指针不是常量
// (*ptr)++; //指针+1了,指向下一个地址了,但其解除引用后依旧是const
ptr--;
ppp=const_cast<int*>(&val);
(*ppp)=23;
cout<<*ppp<<" ;&ppp: "<<ppp<<endl;
cout<<val<<";&val: "<<&val<<endl; //val=13
cout<<"*(&val): "<<*(&val)<<" ;*(int*)(&val): "<<*(int*)(&val)<<endl; //13 ;23
cin.get();
return 0;
} muyu0096 发表于 2016-3-30 20:35
const_cast 运算符,只是改变指针的const属性,但const命名的变量依旧不能改变。
换句话说,就是指针不是c ...
我是使用Qt做的,虽然还是不太理解,但是最终并没有改变const 变量的值。
页:
[1]