const vs非const变量,赋值后没有值变化

时间:2017-11-29 09:55:00

标签: c++ performance const

在C ++中,如果变量的值在整个程序中分配后永远不会改变 VS 如果将该变量设为const,那么可执行代码更快? 编译器如何优化案例1中的可执行代码?

2 个答案:

答案 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