跟我学C++中级篇——const_cast分析

「C++ 40 周年」主题征文大赛(有机会与C++之父现场交流!) 10w+人浏览 457人参与

一、常量处理

开发者们都明白一个道理,能用const限制的访问操作一般尽量限制一下。这样,就会让代码的安全性和稳定性提高一分。但现实世界往往是树欲静而风不止,不是说开发者想怎么样就怎么样。除了有些为了方便自己修改不使用const外,也无法避免别的开发者乱用或不用const。如果说对于新的代码可能还好控制一些,对于很多遗留的代码就不好办了。没人愿意会去读代码然后去加const。这就有可能产生对常量和非常量间的转换,虽然这种转换是一种风险比较大的行为。
另外还有一种情况,C++作为一种“扩展的C”,与C语言打交道的地方非常多,这也会遇到const的处理问题。另外,在C++的重载中,const也是一种形式,这就可能导致一些根本无法预料的问题,一个不小心,就会浪费开发者大量的时间和精力。特别是使用const_cast后,对象的状态在开发者角度发生了改变,如果不加注意,运行的代码路径可能会出现偏差(从常函数转到了普通函数),一些低级问题就涌现了出来。
还有,如果使用const_cast后,分散的常量指针控制,有可能导致不同开发者在维护相同的变量时,产生不正确的数据行为结果。比如一个开发者当常量使用,而另外一个开发者使用const_cast后进行数据的修改。这就会让前者感到很困惑,甚至很难在短时间内定位相关的错误。
种种的上述问题,都表明对常量的处理是一种风险比较大的行为,开发者在应用时,一定要小心应对,不能随意而为之。

二、const_cast分析

const_cast的本质就是告诉编译器对定义的类型限定符(const),要换一个方式来处理其对应的内存。在保证原始数据一致的情况下,只是告诉编译器这块内存已经可以读写。而且需要保证是同一块内存即内存的地址不应发生改变。
说成直白的话,就是常量限定符在被const_cast处理后,已经可以不再受常量的控制了。从多个维度看,它既是常量(原始定义的位置),又不是常量(转换后地址可以被写)。
const_cast存在的目的主要为了处理以下几种状况:

  1. 单向转换只读
    即常量不在原始定义处使用,只转到非常量后读操作
  2. 处理mutable数据
    在特殊情况下,常函数也需要修改数据,那么那些数据可以mutable修饰,以可以被常函数修改
  3. 减少数据的内存处理
    毕竟直接转过去就可以用,不用再重新创建一个新对象,然后再拷贝过去
  4. 增加适当的灵活性
    保证在某些场景下,可以较为灵活的处理业务数据,而不必修改相关的接口
  5. 兼容老的非常量接口或C接口
    在遗留代码或兼容C的接口中,可能存在大量的非const参数应用,而C++中的定义都使用了const,这就需要const_cast

三、应用场景和限制

理解了const_cast的机制,就可以很容易的进行应用,其应用场景主要有:

  1. 接口处理,特别是兼容C接口
// 参数是非 const 的
void not_const_func(char* s);

void const_cpp_func(const char* s) {
    not_const_func(const_cast<char*>(s));
}
  1. 公用代码,非常函数可以调用常函数
class Demo {
public:
  const int *getDataConst() const { return d_; }

  int *getData() { return const_cast<int *>(getData1()); }

private:
  const int *d_ = new int(33);
};
  1. 可预见并可控的常量值转非常量值
    比如一些测试的特定场景以及其它一些情况,对后果或行为结果不太有意义的情况下,都可以进行。特别是在转成非常量指针后进行写入操作,这个行为可能导致不可预知的后果。

其实在上述的说明中,存在着一些限定的条件,主要有:

  1. 可以把常量指针通过const_cast转成非常量指针,但直接这种转换会产生不可预测的行为结果。所以尽量不要这样做。特别是在接口的参数处理上,最好采用重载的形式重新定义
  2. 控制常量指针参数数据的单一性和专有性。不能让一个参数既传入数据也传出数据
  3. 必须修改的数据请使用mutable
class Demo {
private:
    mutable int d_;   
    
public:
    int getData() const {
        return ++d_;
    }
};
  1. 如果一定要使用const_cast,请严格限定其作用域

四、总结

C++语言之所以被广大的开发者诟病,主要原因就是太灵活,而且关键它对一些灵活而产生的结果并不负责任。也就是常说的“未定义或未知结果”。而这种没有明确定义的结果,就可能让一些开发者产生误会,导致有问题的代码不断的出现而无法及时的进行更正。
学习C++语言,要准确理解库和接口的应用形式,这样才能写出健壮的代码。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值