![](/img/trans.png)
[英]In C++ if a pointer is returned and immediately dereferenced, will the two operations be optimized away?
[英]C++: is the if() pointer check optimized?
以下代碼測試2個setter程序的呼叫的時鍾時間。 一個檢查空指針,一個不檢查。 編譯的-O3標志的程序輸出給出相同的時間:
0.000000 ticks (0.000000 secs)
0.000000 ticks (0.000000 secs)
使用-O0標志,時序差異仍然很小
4250000.0000 ticks (4.25000 secs)
4230000.0000 ticks (4.25000 secs)
是由編譯器在for循環中優化的嗎? 如果是這樣,應該如何針對兩者的效率差異測試“真實”世界場景?
class B {};
class A
{
public:
void set( int a ) { a_ = a; }
int get() const { return a_; }
private:
int a_;
};
class A1
public:
A1() : b_(0) {}
void set( int a ) { if( b_ ) a_ = a; }
int get() const { return a_; }
private:
int a_;
B* b_;
};
int main()
{
const int n=1000000000;
clock_t t0, t1;
A a;
A1 a1;
t0 = clock();
for( int i=0; i < n; ++i )
a.set( i );
t1 = clock();
printf( "%f ticks (%.6f secs)\n", (double) t1-t0, ((double) t1-t0) / CLOCKS_PER_SEC );
t0 = clock();
for( int i=0; i < n; ++i )
a1.set( i );
t1 = clock();
printf( "%f ticks (%.6f secs)\n", (double) t1-t0, ((double) t1-t0) / CLOCKS_PER_SEC );
return 0;
}
檢查空指針幾乎可以肯定是一個時鍾周期的操作。 在任何現代處理器上,這將是二十億分之一秒。 我認為這超出了滴答計數器的分辨率(取決於平台,該分辨率為毫秒或微秒)。
如果您真的想知道,請在調試器中查看發出的匯編代碼。
-O3
情況下的測量結果為0,因此顯然編譯器進行了優化,而不僅僅是空指針檢查。 它完全刪除了循環,原因是循環中生成的結果從未使用過。
您確實有a.get();
和a1.get();
在代碼中檢索循環中生成的值,但是同樣,這些函數調用的結果不涉及任何副作用,因此編譯器將其刪除。
如果將這些get()
調用替換為在clock()
調用之后放置的打印語句(以確保時間測量中不包括IO),則會得到不同的結果(我從中刪除了a
和a1
的實際值輸出):
2540000.000000 ticks (2.540000 secs)
0.000000 ticks (0.000000 secs)
因此,第一個循環現在執行一些實際操作,而第二個循環仍被優化(Clang 3.3)。 原因可能是a1._a
的設置取決於指針,該指針已初始化為0
,然后在循環中從未更改。 在a1.set()
的函數調用內聯到主循環中之后,編譯器可以很容易地看到a1._a
的分配將永遠不會發生。
(注意:由於從未實際設置a1._a
,因此打印其值意味着打印從未初始化的變量的值。的確,我得到了一個看起來非常隨機的輸出,當然,嚴格來說,打印該值會調用未定義的值行為。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.