const-correctness可以提高性能吗?

问题描述:

我已经读过很多次,在C或C++代码中强制执行const-correctness不仅是一种关于可维护性的好做法,而且它还可以让您的编译器执行优化。但是,我已经读完了,完全相反,它根本不影响性能。const-correctness可以提高性能吗?

因此,你有没有例子说明const正确性可以帮助你的编译器提高程序的性能?

+42

常量正确性是关于可维护性的最佳实践之一。如果你的C++代码不是const正确的,它基本上是一堆垃圾,等待着灾难发作。它不打算影响性能。 – 2010-08-08 16:23:00

+1

@尼尔·巴特沃斯:不幸的是,情况并非如此。 – Beta 2010-08-08 16:27:31

+3

下面是一个'const'使性能有所不同的例子:http://*.com/questions/1121791/optimisation-of-division-in-gcc。不过,这本质上是一个质量实施问题。 'const'并不能确定编译器*是否能够合法地进行优化,只是编译器版本在缺失时发生错误。 – 2010-08-08 16:34:51

const正确性无法提高性能,因为const_castmutable在语言中,并允许代码一致地破坏规则。这在C++ 11中变得更糟,您的const数据可能会例如成为指向std::atomic的指针,这意味着编译器必须尊重其他线程所做的更改。也就是说,编译器查看它生成的代码并确定它是否实际写入给定变量并相应地应用优化是微不足道的。

这都说,const正确性是一个关于可维护性的事情。否则,您的班级的客户可能会破坏该班级的内部成员。例如,考虑标准std::string::c_str() - 如果它不能返回一个常量值,那么你就可以使用字符串的内部缓冲区了!

出于性能原因,请勿使用const。出于可维护性原因使用它。

在我的经验
+26

“你可以用螺丝刀的内部缓冲区拧紧!” - 关键的是,你可能会意外地将内部缓冲区拧紧。由于'const'引起的编译器错误是路标,说“你在做一些愚蠢的事情”。 – 2010-08-08 16:32:08

+1

@Steve:好点。 +1发表评论。 – 2010-08-08 16:34:44

+4

...和const-casts是路标说:“这个代码的作者正在尝试做一些聪明的事情;-) – 2010-08-08 16:35:40

,没有

对于标量变量,编译器能够确定每当值被改变,进行必要的优化本身。

对于数组指针,常量的正确性不能保证值在存在潜在的混叠问题时确实是常量。因此编译器无法使用const修饰独自执行优化

如果你正在寻找的优化,你应该考虑__restrict__或特殊功能调节器/属性:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

是的,它可以。

大多数const仅纯粹是为了程序员的利益,并且不会帮助编译器进行优化,因为将它们丢弃是合法的,所以它们不会告诉编译器任何有用的优化。然而,一些const不能被(合法)抛弃,这些确实为编译器提供了用于优化的有用信息。

作为示例,可以内联访问用const类型定义的全局变量,而不带const类型的类型不能内联,因为它可能在运行时更改。

https://godbolt.org/g/UEX4NB

C++:

int foo1 = 1; 
const int foo2 = 2; 

int get_foo1() { 
    return foo1; 
} 

int get_foo2() { 
    return foo2; 
} 

ASM:

foo1: 
     .long 1 
foo2: 
     .long 2 
get_foo1(): 
     push rbp 
     mov  rbp, rsp 
     mov  eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address 
     pop  rbp 
     ret 
get_foo2(): 
     push rbp 
     mov  rbp, rsp 
     mov  eax, 2 ; foo2 has been replaced with an immediate 2 
     pop  rbp 
     ret 

在实际应用中,要记住,虽然const可以提高性能,在大多数情况下,它不会也但将改变不会引人注目。 const的主要用途不是优化。


Steve Jessop在他对原始问题的评论中给出了另一个例子,它提出了一些值得一提的问题。在块范围内,编译器可以推断变量是否会发生变化并进行相应优化,而不管const,因为编译器可以看到变量的所有用途。相反,在上面的例子中,不可能预测foo1是否会被突变,因为它可以在其他翻译单元中修改。我想假设有知觉的超级编译器可以分析整个程序,并确定是否有效内联访问foo1 ...但实际编译器不能。