C++编码器军规(003):避免对一个声明为const的变量使用const_cast

军规 避免对一个声明为const的变量使用const_cast


Never use const_cast on an object which is defined to be const

解读


(1)const_cast的作用

const_cast顾名思义,就是转换掉表达式的const性质,比如对于一个字符打印函数的原型如下:

void StringPrint(char *pStr)
{ 
    std::cout << pStr << std::endl;
}

如果我们在上下文中这样使用:

const char * str = "print me";
StringPrint(str);

程序在编译的时候会报错error: invalid conversion from ‘const char*’ to ‘char*’我们把一个只读的指针赋值给可以具有读写属性的函数参数,编译器无法转换,就发生了编译错误。这个时候,我们可以选择这么做:

const char *str = "print me";
StringPrint(const_cast<char *>(str));

const_cast帮助我们转换掉了str指针的const性质,使得我们可以顺利地使用StringPrint函数。总结一下const的作用如下:

  • const_cast用来转换掉表达式(变量、指针)的const性质
  • 只有const_cast才能转换掉表达式的const性质,其它的转换(如static_cast)都会出错

(2)使用const_cast的风险
const_cast虽然在去掉变量及表达式const性质上面起到独一无二的作用,但是这么做本身也是不安全的。一个被const修饰的变量本来就是设计为不可写的,并且在编译期间被编译器存放在只读区域的。我们强制将这个变量或表达式的const属性去掉,首先就违背了在定义这个变量期间的意图,其次把一个本来存储在只读段的变量强制去掉也是非常不安全的。

(3)关于const_cast的深入思考
对于上文中关于StringPrint的函数,除了使用const_cast的之外,我们其实可以修改StringPrint函数使其可以接受const属性,比如:
void StringPrint(const char *str);
这样我们就可以这样调用了:

const char * str = "const cast example"
StringPrint(str);

也就是说我们在使用const_cast之前,考虑一下是不是设计上有问题,是不是可以通过改善设计去避免使用const_cast。记住下面一句话:

Casting away const is a sign of bad design and should be avoided altogether!

(4)最佳实践

  • 尽量不要使用const_cast
  • 如果觉得需要使用const_cast,考虑一下是否可以通过更改设计去避免
  • 如果非要使用不可,这种场合只能用const_cast, 其它的(如static_cast)都会出错

你可能感兴趣的:(C/C++)