2013-07-24 47 views
0

我已經很長一段時間,所以我覺得傻,不知道這種編程C++,但...初始化方法與構造函數加賦值 - 任何性能差異? (C++)

我經常寫性能敏感的代碼,當我做我會盡量避免堆分配爲儘可能多。爲此,我經常重新使用預先分配的小對象數組,而不是爲每個單獨的對象調用new和delete。

在這種情況下,我通常這樣做:

class MyClass 
{ 
private: 
    int x, y; 

public: 
    inline void Set(_x, _y) { x = _x; y = _y; } 
}; 

...

MyClass &objectToReuse = someArray[someIndex]; 

objectToReuse.Set(someXValue, someYValue); 

不過我懷疑這更好看的版本會產生相同的代碼:

class MyClass 
{ 
private: 
    int x, y; 

public: 
    inline MyClass(_x, _y) : x(_x), y(_y) {} 
}; 

...

MyClass &objectToReuse = someArray[someIndex]; 

objectToReuse = MyClass(someXValue, someYValue); 

一個現代的C++編譯器會「得到」它,還是會構造一個臨時對象然後複製它?

+0

如果您的對象很簡單,它會使0差異,並可能會產生類似的,如果不相等,**優化**代碼。如果在構造函數或非默認賦值運算符(如輸出或更改外部存儲器)中有副作用或者對象使用虛函數,則使用setter會產生更高效的代碼。但是,我很確定它不會是你的程序的性能問題=)。 – UnknownGosu

回答

1

是的,一個好的編譯器會消除這種情況下的額外開銷。

我說「在這種情況下」,因爲它確實非常依賴於在構造函數中發生了什麼(以及賦值運算符 - 它在下面說「構造函數/構造,讀作爲」或賦值運算符「)。構造函數影響(或「可能影響」)全局狀態,那麼編譯器不能刪除構造,影響全局狀態是讀取或寫入文件,更新全局變量,幾乎所有對編譯器不會「知道「(沒有源代碼)會導致構造/複製消除」失敗「

當然,如果構造函數/副本沒有被消除,使用setter的代碼可能會更有效。在實際情況下,確切的衡量標準只能通過基準確定,因爲它確實如此通常很難判斷一條或多條代碼實際上在優化編譯時會產生什麼樣的效果 - 一些非常簡單的外觀有時會產生相當大的影響,看起來很複雜的東西可以(儘管不太經常=最終不會花太多時間所有。

+0

感謝您的回答,這就是我所設想的。聽起來像構造函數/複製消除將適用於我做這種類型的「啞」類的每一個案例;它通常是矢量類,這些類與任何全局狀態沒有關係,並且是完全獨立的。 – Simplex