2011-07-17 81 views
2

我有一個統計管理器,通過測量執行方法所需的時間來檢查我的應用程序性能。它的用法如下:MyClass(expr)之間的作用域差異;和MyClass myObject(expr);

myStatManager.StartStat("Rendering"); 
Render(); 
myStatManager.StopStat("Rendering"); 

輸出到屏幕會告訴我該方法花了多長時間。

爲了方便起見,我寫了一個虛擬對象,在對象被創建和銷燬時調用這兩個方法。這使我可以使用C++範圍規則來處理我的優勢,只需輸入一次統計跟蹤行而不是上面的兩次。

class ScopedStat 
{ 
    string label; 
    ScopedStat(string inLabel): label(inLabel) { myStatManager.StartStat(label); } 
    ~ScopedStat() { myStatManager.StopStat(label); } 
} 

預期的用法如下:

{ 
    ScopedStat("Rendering"); 
    Render(); 
} 

然而,這不起作用,因爲也許是編譯器什麼的優化了ScopedStat對象了。所報告的時間僅爲毫秒的幾分之一,遠不及應該呈現的時間。我的問題是,爲什麼這種方式不起作用?這個對象不會在範圍的末尾被銷燬嗎?

編輯:我已經找到了解決辦法:

{ 
    ScopedStat ss("Rendering"); 
    Render(); 
} 

這按預期工作 - 對象得到僅在大括號的結束時被銷燬。雖然,我仍然想知道爲什麼。

注意:使用Microsoft Visual Studio 2008 C++;

編輯2:啊,我現在明白了,除非我將我的對象綁定到變​​量,否則在表達式評估之後它會被銷燬。感謝你的幫助。

有誰知道爲什麼C++是這樣寫的?什麼用途是一個臨時變量,如果它立即被破壞?

+0

我認爲他們是相關但不重複。這個問題關於'MyClass(expr);'和'MyClass myObject(expr)'之間的區別,答案是關於第一種情況的臨時變量。而潛在的重複是特別要求關於臨時性的生命週期。 – TooTone

回答

1

您已經創建了一個超出範圍的臨時對象,也就是下一行開始執行時。以便在渲染之前完成啓動和停止。

3

如果您不使用對象的標識符,它將變爲臨時對象並在其所屬的表達式結束後被銷燬。換句話說,它具有單一表達的範圍。

您必須爲您的對象命名直到括號範圍的末尾。

ScopedStat stat("Rendering"); 
4
{ 
    ScopedStat("Rendering"); 
    Render(); 
} 

然而,這不起作用,因爲也許是編譯器或某物 優化ScopedStat對象了。報告的時間是幾分之一毫秒的幾分之一,幾乎不需要渲染。 我的問題是,爲什麼這種方式不起作用?這個對象是否在範圍的最後被銷燬了 ?

您沒有創建一個正常的變量,只是碰巧沒有名字。您正在創建一個臨時,並且它在宣佈它的full-expression的末尾不再存在。(也就是說,被調用Render()前,ScopedStat來了又走了。)

給它一個名字。


要回答你的最後一個問題,這使得當你做這樣的事情非常有意義:

doFoo(ScopedStat("Rendering")); 

臨時生活,只要不以doFoo通話是恰到好處。

相關問題