在C ++中,如果变量的值在整个程序中分配后永远不会改变 VS 如果将该变量设为const,那么可执行代码更快? 编译器如何优化案例1中的可执行代码?
答案 0 :(得分:5)
聪明的编译器可以理解变量的值永远不会改变,从而优化相关代码,即使程序员没有明确的const
关键字也是如此。
至于你的第二个问题,当你将一个变量标记为const
时,后面的可能发生:“编译器可以通过不向这个变量提供存储来优化掉这个const而是将它添加到符号表中。因此,后续读取只需要间接到符号表而不是从内存中获取值的指令“。阅读What kind of optimization does const offer in C/C++? (if any)中的更多内容。
我说可能,因为const
并不意味着这是一个确定的常量表达式,这可以通过使用constexpr
代替,正如我解释的那样。
通常,在使用const
关键字时,您应该考虑更安全的代码,而不是更快的代码。因此,除非您为更安全和更易读的代码执行此操作,否则您可能会成为过早优化的受害者。
加成:
C ++提供constexpr
关键字,允许程序员将变量标记为标准调用常量表达式。常量表达式不仅仅是常量。
在Difference between `constexpr` and `const`和When should you use constexpr capability in C++11?
中了解详情PS:Constness阻止移动,因此使用const太过宽松可能会使代码执行得更慢。
答案 1 :(得分:1)
在哪种情况下可执行代码更快?
使用const
时代码更快,因为编译器有更多优化空间。请考虑以下代码段:
int c = 5;
[...]
int x = c + 5;
如果c
不变,则只需将10分配给x
。如果c
不是常量,那么它依赖于编译器是否可以从c
事实上不变的代码中扣除。
编译器如何优化案例1中的可执行代码?
如果变量不是常量,编译器很难优化代码。变量的范围越广,编译器就越难以确保变量不会发生变化。
对于简单的情况,如局部变量,具有基本优化的编译器将能够推断出变量是常量。所以它会把它视为常数。
if (...) {
int c = 5;
[...]
int x = c + 5;
}
对于更广泛的范围,如全局变量,外部变量等,如果编译器无法分析整个范围,它会将其视为普通变量,即分配一些空间,生成加载和存储操作等。 / p>
file1.c
int c = 5;
file2.c
extern int c;
[...]
int x = c + 5;
还有更积极的优化选项,例如链接时优化,这在这种情况下可能会有所帮助。但是,在性能方面,const
关键字仍然有用,特别是对于具有宽范围的变量。
编辑:
文件const.C:
const int c = 5;
volatile int x;
int main(int argc, char **argv)
{
x = c + 5;
}
汇编:
$ g++ const.C -O3 -g
拆卸:
5 {
6 x = c + 5;
0x00000000004003e0 <+0>: movl $0xa,0x200c4a(%rip) # 0x601034 <x>
7 }
所以我们只需将10(0xa)移动到x。
档案nonconst.C:
int c = 5;
volatile int x;
int main(int argc, char **argv)
{
x = c + 5;
}
汇编:
$ g++ nonconst.C -O3 -g
拆卸:
5 {
6 x = c + 5;
0x00000000004003e0 <+0>: mov 0x200c4a(%rip),%eax # 0x601030 <c>
0x00000000004003e6 <+6>: add $0x5,%eax
0x00000000004003e9 <+9>: mov %eax,0x200c49(%rip) # 0x601038 <x>
7 }
我们加载c
,添加5并存储到x
。
因此,即使您可以看到非常积极的优化(-O3)和您可以编写的最短程序,const
的效果也非常明显。
g ++版本5.4.1