const关键字何时会降低性能而非优化性能?附代码示例
作为经常和编译器优化打交道的老鸟,我得说const确实是个好用的工具——它给编译器传递语义信息,帮着做常量折叠、缓存优化这些事,但用错地方,真的会帮倒忙。以下是几个典型的坑:
当const变量存在被间接修改的风险时,编译器不敢缓存
比如你定义了const int x = 10;,但偷偷用int* p = (int*)&x;去改它(这本身是未定义行为,但编译器未必能揪出来)。这时候编译器为了保证const的“只读”语义,每次读x都得从内存重新捞,不敢把它存在寄存器里——本来能省的内存访问,反而变多了,性能自然降下来。const修饰的大结构体参数,被迫做冗余拷贝
如果函数参数是const struct HugeStruct s,而函数内部需要临时改s里的某个字段(哪怕只是临时用一下),你就得先复制整个结构体到局部变量里。结构体越大,这个拷贝的开销就越夸张,完全是没必要的性能损耗。嵌入式场景下,把频繁访问的变量标成const
在嵌入式系统里,const变量一般会被放到只读存储区(ROM/Flash),而ROM的访问速度比RAM慢得多。要是你在一个几万次的循环里频繁读这个const变量,比如判断阈值,那每次都得从ROM取数据,比把变量放RAM里慢一大截,循环直接被拖慢。用const_cast强行修改const变量,打乱编译器优化逻辑
为了改const变量而用const_cast去掉const属性,编译器的优化器直接懵了——它本来以为这个变量不会变,做了常量折叠之类的优化,结果你偷偷改了,不仅可能出逻辑错误,生成的代码也会变得冗余,完全发挥不出优化效果。
先看代码里的几个关键点:
静态数组
huffman_node_list2的const风险
这个数组是static的,存在静态存储区。如果有人脑子一热把它声明成static const struct huffman_node huffman_node_list2[...],那后面的huffman_node_list2[k + i] = ...赋值直接就炸了——const变量不能被修改。要是强行用const_cast去绕,就会触发上面说的未定义行为,编译器的优化也会乱套,性能肯定受影响。k变量的const使用
代码里k = TSIZE_MAX * 2,要是把k改成const int k = TSIZE_MAX * 2;,其实是没问题的——因为TSIZE_MAX是宏常量,k的值编译期就能算出来(512),编译器会直接把k替换成常量值,反而能优化索引计算,不会有性能问题。但如果k是依赖运行时参数的const变量,那情况就不一样了,但这里显然是编译期常量,所以const在这里是安全的。结构体赋值的const影响
代码里的结构体赋值huffman_node_list2[k + i] = huffman_node_list2[i + 1];,如果huffman_node的成员被标成const,比如const int weight;,那这个赋值操作直接失败——因为不能修改const成员。这时候要么去掉const,要么只能用指针操作,反而增加代码复杂度和性能开销。
内容的提问来源于stack exchange,提问作者macxfadz

