c++ 中const关键字定义属性(Visual Studio又在给我们添麻烦啦)

在c++中const关键字是一个常用的点,关于const关键字的介绍网上也是比比皆是,今天写代码过程中发现一个问题在网络中没有找到,所以记载一哈。

问题发现

在c++中有四种类型转换的方式,分别是static_cast、dynamic_cast、const_cast、reinterpret_cast,关于各种转换方式的区别,可以查看别的博客,我们今天关注的是const_cast转换方式。const_cast转换方式的功能是将对象的const属性去除,下面看代码。

#include<iostream>
using namespace std;

int main() {

    const int a = 0;//定义一个常量整形
    int & r = const_cast<int &>(a);//通过const_cast去除const属性
    r++;//将r自增1
    cout << a << endl;//输出0
    cout << r << endl;//输出1
    return 0;
}

这个程序的输出结果已经注释在代码中了,代码中确实使用了const_cast进行去除了,为什么打印的结果还是0呢,难道是const_cast的功能失效了?下面看另一段代码。

#include<iostream>
using namespace std;

int main() {
    int i;
    cin >> i;//这里我们随意输入,输入一个0吧
    const int a = i;
    int & r = const_cast<int &>(a);
    r++;
    cout << a << endl;//输出1
    return 0;
}

经过这段代码可以看出来,const_cast确实将a的const属性去除了,那为何第一段代码出问题了呢?为何打印r的时候又正确了呢?

问题分析

分析两段代码,唯一的区别就是对a的赋值,第一段代码中,直接使用的是一个常量,第二段代码中则是通过变量i,运行的时候输入的,所以可能是这个原因造成的。在以const int a=0的方式进行定义的时候,编译器会在编译阶段,将a直接替换成0,所有的出现a的地方都变成了0,那么输出a的时候就直接语句变成了输出0,所以在去const之后,即使正确的修改了a的值,输出语句也无法正常执行。但是第二个是在运行时期确定的,a的定义位置也是栈中,所以在使用输出语句的时候,输出语句还是指向a的地址的,所以可以正确输出。所以问题的关键应该不是const_cast没有起作用,而是编译器给我们做了一个坏事。

分析验证

查看第一段代码中的a的地址和b的地址:

int main() {
    /*int i;
    cin >> i;*/
    const int a = 0;

    int & r = const_cast<int&>(a);
    r++;

    cout << &a << endl;//00AFF7D4
    cout << &r << endl;//00AFF7D4
    return 0;
}

说明这里的r并不是副本,而是真正的a,那么为何会输出0呢?再看调试时的状态,如下图:
这里写图片描述
下图我们可以看出,此时a的值确实已经变成了1,但是输出的确实为0,真是一个匪夷所思的操作呀。 看来编译器翻译是有问题的,我们来查看下汇编代码,如下图:
这里写图片描述
如图所示,问题的源头显示出来了!在地址为00A51EE1处,代码为push 0,此处是为cout赋予参数的,但是居然直接是0,而没有引用a这个变量,看来编译器把const不当变量呀。
现在问题解决了,不是const_cast的问题,而是vs在编译阶段做的替换的问题,这应该也是vs上的一个bug吧,希望大家coding的时候可以注意一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值