2010-08-08 87 views
58

我已經讀過很多次,在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://stackoverflow.com/questions/1121791/optimisation-of-division-in-gcc。不過,這本質上是一個質量實施問題。 'const'並不能確定編譯器*是否能夠合法地進行優化,只是編譯器版本在缺失時發生錯誤。 – 2010-08-08 16:34:51

回答

50

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

6

,沒有

對於標量變量,編譯器能夠確定每當值被改變,進行必要的優化本身。

對於數組指針,常量的正確性不能保證值在存在潛在的混疊問題時確實是常量。因此編譯器無法使用const修飾獨自執行優化

如果你正在尋找的優化,你應該考慮__restrict__或特殊功能調節器/屬性:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

13

是的,它可以。

大多數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 ...但實際編譯器不能。