关于常量指针的转换问题

文章讨论了const_cast在C++中的使用,特别是在处理const对象和成员函数时的情况。通过示例代码展示了const_cast如何改变const对象的访问权限,以及const引用和指针在内存中的表示。尽管const_cast允许修改const对象,但这样做可能会导致未定义的行为,尤其是在尝试修改const对象的原始状态时。
摘要由CSDN通过智能技术生成

const_cast

    在我们的coding当中,经常使用到const来修饰形参,主要是为了保证在函数里面不要对其进行修改,但是呢?这种操作也会导致以下情况:


class AA {
    private:
        int _val;
    public:
        int GetSize() { return 43; }
        void SetVal(int val){ _val = val;}
        int GetVal() {return _val;}
    
};

class BB {
    public:
        int GetSize() { return 33; }
        bool isEauql(const AA &a) const {
            
            AA &a1 = const_cast<AA &>(a);
            BB &b1 = const_cast<BB &>(*this); 
            BB *c1 = const_cast<BB *>(this);


            // 获取常量a的地址和获取将a转换成非常量后的地址
            std::cout<<&a<<std::endl;                       // 编译运行后,得到地址为:0x7ffd8f5d7088
            std::cout<<&a1<<std::endl;                      // 编译运行后,得到地址为:0x7ffd8f5d7088
            
            // 转换const this指针变成非常量指针后,获取其地址
            std::cout<<&c1<<std::endl;                      // 编译运行后,得到地址为:0x7ffd8f5d7048

            // 获取this指针的地址
            std::cout<<this<<std::endl;                     // 编译运行后,得到地址为:0x7ffd8f5d708f

            // 转换const this指针变成非常量引用后,获取地址
            std::cout<<&b1<<std::endl;                      // 编译运行后,得到地址为:0x7ffd8f5d708f

            // 不可以通过a去修改AA类中的属性值
            a.SetVal(2);
            
            // 可以通过转换常量a后的非常量引用a1来修改AA类中的属性值
            a1.SetVal(2);
            std::cout<<a1.GetVal()<<std::endl;

            if (a1.GetSize() == b1.GetSize()) {
                return true;
            }
            return false;
        }
};

int main() {

    BB b;
    AA a;

    std::cout << &a <<std::endl;         // 编译运行后,得到地址为:0x7ffd8f5d7088
    std::cout<<b.isEauql(a)<<std::endl;    
}

分析上面的代码:

main函数

main函数中定义了两个类对象,分别是a和b,此时在内存的栈区域会给这两个变量开辟一块内存来存放它们。

isEqual函数

当对象b调用函数isEqual(a)之后,在isEqual函数中可以打印形参a的地址可以看到,这两个地址是一模一样的,这是因为引用只是给变量起了个别名,所以它们的地址是相同的,然后我们再打印通过const_cast转换a后的a1非常量引用的地址,可以看到这两个的地址是一致的(this和b1也是一致的),但是在实际的编译器地址中引用是需要占有一定内存的,这个内存的大小和指针大小一致,只是编译器做了一些手脚,让我们看他们的地址是一致的。

(1)我们定义了c1指针来指向const this指针转换成非常量的内存,可以看到这里的c1跟this的地址是不相同的,因为指针是自己占据了内存,所以我们可以通过转换后的c1来进行调用BB类中的属性或者方法函数,但是不能通过const this指针来调用BB类中的属性或者方法。

(2)我们定义的a1和b1这两个引用分别作为类对象a和this的非常量引用,虽然我们在打印a和a1的地址是一样的,b1和this的指针是一样的,但是在实际的编译器中a和a1,b1和this是不相同的,在实际的内存中是长这样的:

所以才导致我们a和this不能直接调用类中的属性和方法,因为它本身还是常量,而a1和b1就可以调用并且修改.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三贝勒文子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值
>