鱼C论坛

 找回密码
 立即注册
查看: 2469|回复: 2

关于const_cast问题?

[复制链接]
发表于 2016-3-29 11:44:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
请问,ncref和val的地址一样,使用ncref指针修改值之后为什么val值不变?
4DF1.tmp.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-3-30 20:35:24 | 显示全部楼层
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的反汇编代码,
00F942DC  push       0Dh
00F942DE  mov         ecx,dword ptr [__imp_std::cout (0F9A300h)]  
你看这里压入的是 0Dh,也就是13这个字面变量
而普通的变量打印的汇编代码则是
00F9428C  push        eax  
00F9428D  mov         ecx,dword ptr [__imp_std::cout (0F9A300h)]  
00F94293  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0F9A2FCh)]  
压入的是eax(或别的寄存器),寄存器里存着变量的值,也显示出是一个普通变量。
看的出来,该地址的值虽然被改变了,但val依旧被解释为字面常量,并且在编译过程中已经被替换为13了,也正因为编译时就是13,所以编译器是不允许你改变val的值的,否则就乱套了。

但也有一个很有意思的事情,*(&val)的值虽然为13不变,但*(int*)(&val)的值却为23.这里的强制类型转换,应该彻底抹去了指针和val变量的关系。看汇编代码,也是体现出前者是字面值,而后者是一个变量。
        cout<<"*(&val): "<<*(&val)<<" ;*(int*)(&val): "<<*(int*)(&val)<<endl;        //13 ;23
00F94318  mov         esi,esp  
00F9431A  mov         eax,dword ptr [__imp_std::endl (0F9A304h)]  
00F9431F  push        eax  
00F94320  mov         edi,esp  
00F94322  mov         ecx,dword ptr [val]                  //对应源代码 *(int*)(&val)
00F94325  push        ecx                                          //压入的是寄存器
00F94326  push        offset string " \xa3\xbb*(int*)(&val): " (0F97AFCh)  
00F9432B  mov         ebx,esp  
00F9432D  push        0Dh                                          //对应源代码 *(&val),压入的是字面常量0Dh
00F9432F  push        offset string "*(&val): " (0F97898h)  
00F94334  mov         edx,dword ptr [__imp_std::cout (0F9A300h)]


在你的程序基础上我增加了若干代码,我觉得基本上说明了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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-31 13:40:28 | 显示全部楼层
muyu0096 发表于 2016-3-30 20:35
const_cast 运算符,只是改变指针的const属性,但const命名的变量依旧不能改变。
换句话说,就是指针不是c ...

我是使用Qt做的,虽然还是不太理解,但是最终并没有改变const 变量的值。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-26 22:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表