- 论坛徽章:
- 8
|
const的含义就是“常量”;是常量,标准就允许编译器做常量优化。
允许做常量优化,就是允许编译器无条件假设这个值不会变化,也就是说“所有基于这个值没有被修改过”这个假设的优化都是对的。
换句话说,const int a = 3 在编译器内部完全可以当成 #define a 3 来实现;除了允许&操作和需要做类型检查,两者没有任何差别。
所以,即使你用const_cast修改了a的值,整个程序里所有引用到a的地方仍然可以直接用3替换。
甚至于,我曾举过这样的例子:
void err_strcat(const string a, const string b)
{
*((string *)&a) += b;
}
//main
string x = "123";
string y = "456";
err_strcat(x, y);
显然,err_strcat是个传值的实现,所以这个strcat应该无法完成它的任务,x的值也不会受到任何影响。
但事实上,由于常量优化,编译器可以认为这个函数内部不会修改x和y,所以它可以不构造临时对象(以节约开销),而是把x的引用直接传进去!
如果你没有强行突破防御,那么这个优化显然不会出问题;但一旦你用了const_cast或c风格类型转换,如同这个err_strcat一样,那么执行后x的值就可以是"123456"。
不仅如此。
由于err_strcat声明它不会修改x,所以后面引用x时,编译器可以一直假设它没被改变——注意string不是原生类型,所以可能无法测试这个特性;改成const char *应该可以测到——这可以导致问题被隐藏很久,然后以一种稀奇古怪的方式暴露出来。
——这个现象和编译器、编译器的优化参数都相关。
所以,不要试图绕过const的限制,除非你确切知道自己在做什么。 |
|