我有一個指針int* p
,並在循環中做一些操作。我不修改內存,只是閱讀。如果我將const
添加到指針(這兩種情況下,const int* p
和int* const p
),它可以幫助編譯器優化代碼嗎?可以給指針添加'const'來幫助優化嗎?
我知道const
的其他優點,比如安全性或自我記錄,我問這個特殊情況。改寫這個問題:const
可以給編譯器提供任何有用的信息嗎?
我有一個指針int* p
,並在循環中做一些操作。我不修改內存,只是閱讀。如果我將const
添加到指針(這兩種情況下,const int* p
和int* const p
),它可以幫助編譯器優化代碼嗎?可以給指針添加'const'來幫助優化嗎?
我知道const
的其他優點,比如安全性或自我記錄,我問這個特殊情況。改寫這個問題:const
可以給編譯器提供任何有用的信息嗎?
雖然這很明顯是特定於實現,但很難看出如何將指針從int*
更改爲int const*
可以提供編譯器本來不知道的任何其他信息。
在這兩種情況下,在執行循環期間,指向的值都可能會發生變化。
因此,它可能不會幫助編譯器優化代碼。
這簡直是錯的; 'int const *'等同於'const int *',它不會指向可寫內存。 (你的意思可能是'int * const') – 2013-12-15 02:37:56
@JoSo:不,這是正確的。所有'int const *'指出的是'int'不能通過特定的指針修改。如果'int'最初是非const的,那麼它可以被代碼的另一部分修改,或者可以在轉換後由代碼的相同部分修改。 – Mankarse 2013-12-15 22:37:08
我的回答錯誤了,無法回顧這是怎麼回事。對不起。更糟糕的是,除非答案被編輯,否則顯然不允許刪除(向下)投票...... :( – 2013-12-16 00:02:57
它可以幫助或它可以沒有區別或它可以使情況變得更糟。要知道的唯一方法是嘗試並檢查發出的機器代碼。
現代編譯器非常聰明,所以他們經常可以推斷出沒有任何限定符的內存沒有改變(如果沒有代碼編寫方式更容易分析,他們可以推斷出許多其他優化是可能的),但它們相當複雜,所以有一個很多缺陷,並且往往無法在每一個機會上優化每一件可能的事情。
你有什麼可以讓它變得更糟的例子嗎? – 2012-01-31 11:00:18
@Jakub M .:不是針對這個特定的情況,但是當編譯器無法發出最優代碼時,我已經看到了幾十個案例。 – sharptooth 2012-01-31 11:28:21
*它可以使情況變得更糟*除非有一個例子證明,'const'可以沒有區別或*有一些*區別,它們之間的差異可以忽略不計,因此不會將其用作優化標準,它只能用於編寫更正確的可維護代碼。 – 2012-01-31 11:38:51
不可以。使用const就不會爲編譯器提供任何可用於優化的信息。
理論上,對於編譯器來說,優化器必須能夠證明沒有人會在你的const指針上使用const_cast
,但無法證明變量永遠不會被寫入。這種情況極不可能。
香草薩特涵蓋這是更深入他的Guru of the Week列之一。
)如果編譯器*能夠證明所有附加信息,那麼它不再需要'const'限定。即使那樣'const'也不會幫助優化。 – Mankarse 2012-01-31 11:21:55
@Mankarse:除非出於一些愚蠢的特定於實現的原因,例如除非指針是const限定的,否則一個特定的優化器不會干擾分析。但是你說的話仍然正確,因爲根據我的論點*任何*都會影響優化 - 變量名稱中的元音數量,或者是否縮進製表符和空格。唯一的問題是,優化程序在某些情況下忽略某些潛在有用的信息而非其他情況的可能性有多大。 – 2012-01-31 12:32:45
我認爲編譯器不能在你的場景中做很多事情。您的指針聲明爲const int * const p
並不能保證內存無法在外部進行更改(例如,由另一個線程。因此,編譯器必須生成讀取循環的每次迭代中的內存值的代碼。
但如果你不會寫入到內存的位置和你知道,沒有其他的代碼會,那麼你可以創建一個局部變量,並用它與此類似:
const int * p = ...
...
int val = *p;
/* use the value in a loop */
for (i = 0; i < BAZILLION; i++)
{
use_value(val);
}
不僅可以幫助潛在的代碼讀者看到val
在循環中未發生更改,而且還使編譯器有可能進行優化(例如,在寄存器中加載val
)。
編譯器通常不會考慮其他線程,除非您專門添加volatile。任何函數調用都會阻礙。 – 2012-01-31 14:01:40
@PerJohansson:你可能是對的。無論如何,另一個線程只是一個例子。任何函數調用的副作用也是一個很好的例子。我只想指出,編譯器執行的任何優化必須(並且確實!)保留了代碼的原始語義,而優化循環內部的內存讀取當然不會,因此也不會執行。但是由於沒有合法的方法可以在外部(函數體外部)更改'val',因此編譯器可以自由優化。 – 2012-01-31 14:16:00
正如其他人所說的,使用const
不太可能幫助編譯器優化您的循環。
但是,它可能會幫助優化代碼以外的循環,或者在調用const限定方法的位置或者接受const參數的函數。
這很可能取決於編譯器是否可以證明它允許消除冗餘負載,移動它們或緩存計算值而不是重新計算它們。
證明這一點的唯一方法仍然是對配置文件進行配置和/或檢查,但這正是您應該查找的位置。
你不說你正在使用哪種編譯器。但是,如果你正在閱讀和寫作內存,你可以從使用「限制」或類似的東西中受益。編譯器不知道你的指針是否是別名相同的內存,所以任何商店經常強制再次加載其他值。 「restrict」告訴編譯器指針不會發生混疊,並且可以繼續使用在後續寫入之前加載的值。避免別名問題的另一種方法是將您的值加載到局部變量中,然後在編寫之後編譯器不會被強制重新加載。
你真的是指'int const * p'嗎?或者'int * const p'?什麼循環?你在迭代什麼? – 2012-01-31 10:46:18
你可以做到這一點,並比較生成的代碼: - ? – cnicutar 2012-01-31 10:47:05
確定給定的CPU,編譯器,操作系統等的唯一方法是對其進行基準測試,結果將僅適用於該特定配置。這聽起來像是對我來說過早的優化。 – 2012-01-31 10:49:41