2009-09-15 49 views
8

我想知道在C++中編寫「全能」類是否以及如何實際影響性能。C++:BIG類的性能影響(有很多代碼)

如果我有例如,一個類,只有uint x; uint y;作爲數據,並且幾乎定義了數學可以做到的一切方法。其中一些方法可能很大。 (copy-)構造函數只不過是初始化兩個數據成員而已。

class Point 
{ 
    int mx; int my; 
    Point(int x, int y):mx(x),my(y){}; 
    Point(const Point& other):mx(other.x),my(other.y){}; 
// .... HUGE number of methods.... 
}; 

現在。我加載一個大的圖像,並創建一個爲每個像素,東西em到一個向量和使用他們。 (比方說,所有的方法都會被調用一次) 這只是一個愚蠢的例子!

沒有方法但是有很多實用功能,它會比同一個類慢嗎?我不是以任何方式談論虛擬功能!我的動機是:我經常發現自己寫了很好的和相對強大的類,但是當我必須像上面例子中那樣初始化/使用它們時,我會感到緊張。 我想我不應該。

什麼,我認爲我所知道的是:

  1. 方法在內存中只有一次存在。 (優化放在一邊)
  2. 分配 只發生數據 成員,並且它們是 複製的唯一東西。

所以它應該沒關係。我錯過了什麼嗎?

+2

另請參閱:http:// stackoverflow。com/questions/648647/in-c-where-in-memory-are-class-functions-put – 2009-09-15 08:44:03

回答

10

你說得對,方法只在內存中存在一次,它們就像普通函數一樣,隱藏了一個額外的參數。

當然,只有數據成員都採取了在賬戶分配,那麼,繼承可能引入一些額外的師生比爲vptrs的對象大小,但不是什麼大不了的

1

如果你是真正的擔心,你可以告訴你的編譯器內聯構造函數。這個優化步驟應該爲您提供乾淨的代碼和乾淨的執行。

1

這些代碼2位是相同的:

Point x; 
int l=x.getLength(); 

int l=GetLength(x); 

鑑於類Point具有非虛擬方法的getLength()。第一次調用實際上調用了int getLength(Point &this),與我們在第二個示例中所寫的一樣,簽名相同。 (*)

如果你調用的方法是虛擬的,這當然不適用,因爲一切都會經過一個額外的間接級別(類似於C-style int l=x->lpvtbl->getLength(x)),更不用說了對於你實際上有3個像素的每個像素有2個int,額外的一個是指向虛擬表的指針。 (*)這不完全正確,「this」指針是通過一個cpu寄存器而不是通過堆棧傳遞的,但是這種機制可以很容易地以任何方式工作。

1

第一:不要過早優化。第二:乾淨的代碼比優化的代碼更易於維護。

類的方法有隱藏這個指針,但你不應該擔心它。編譯器大多數時間都是通過寄存器來傳遞它。

繼承和虛函數在適當的調用中引入了間接指針(繼承=構造函數/析構函數調用,虛函數 - 函數的每個函數調用)。

短:你沒有創建

  • 對象/破壞往往可以有虛擬方法,繼承等等,只要它有利於設計。
  • 您創建/銷燬的對象通常應該很小(很少數據成員),並且不應該有很多虛擬方法(最好根本不會 - 性能明智)。
  • 嘗試內聯小方法/構造函數。這將減少開銷。
  • 如果您沒有達到預期的性能,請進行乾淨的設計和重構。

關於具有大或小接口的類有不同的討論(例如Scott Meyers(More)Effective C++ Books - 他選擇最小接口)。但這與表演無關。

+0

認爲你的意思不是在你的第二點。同樣在第二點中,我認爲虛擬方法很少,虛擬調用速度較慢,因此調用大量虛擬方法會產生一些(小)性能問題。 – Elemental 2009-09-15 09:41:45

+0

謝謝 - 當然你是對的。如果你有很少的好處。方法,大多數方法調用都是直接的(對vtbl沒有間接的)。如果你設法沒有任何好處的課堂。功能,在施工過程中不得設置vtbl。 – 2009-09-15 09:53:50

6

您已經有了一些相當不錯的技術建議。我想拋出一些非技術性的東西:正如STL向我們展示了所有人,在成員函數中執行所有操作可能不是實現此目的的最佳方式。我沒有提到爭論,而是提到斯科特邁爾斯關於這個問題的類文章:How Non-Member Functions Improve Encapsulation

儘管技術上應該沒有問題,但您仍然可能想從設計POV中查看您的設計。

+0

你指出了一篇引人入勝的文章。但我擔心的是,這些人的編碼似乎與大多數正常人相比差別很大。我喜歡成員函數,因爲在每一個值得注意的IDE中,他們都會向我提出並告訴我該類可以做什麼。這對於非會員非朋友功能來說並不可行。 – AndreasT 2009-11-11 10:02:34

+0

如果一個免費函數不能告訴你它做了什麼,那麼它需要一個更好的名字。 – sbi 2009-11-11 13:24:53

+0

不是我的意思。一個IDE提供了類。,它可以減少手冊中的慢速查找。免費功能不顯示在那裏。我可以爲他們做一個搜索,但這比鍵入'更麻煩'。並等待半秒鐘。這就是爲什麼人們只看「壞風格」類的圖書館而沒有大量模板魔法和分散界面的原因之一。每個攀登提升掌握高峯的人都可以爲自己的成就感到自豪,但只能羨慕圖書館,這些圖書館可以在沒有大驚小怪的情況下通過信息進行操作。 – AndreasT 2010-05-25 07:25:56

0

我創建了與您相同的點類,除了它是模板類並且所有函數都是內聯的。我希望看到性能提升不會因此而下降。但是,尺寸爲800x600的圖像將具有480kpixels,並且其存儲器打印將接近4M而沒有任何顏色信息。不僅僅是內存,而且初始化480k對象將花費太多時間。因此,我認爲這不是一個好主意。但是,如果您使用此類來轉換圖像的位置,或將其用於圖形圖元(線條,曲線,圓圈等)

0

我同意上面的評論wrt:性能和類佈局,並且希望添加尚未陳述的關於設計的評論。

對我來說感覺就像你在使用你的Point類超過它的真實設計範圍。當然,可以用那種方式,但是應該是呢?

在過去的電腦遊戲工作中,我經常遇到類似的情況,通常最好的最終結果是,當進行專門的處理(例如圖像處理)時,需要專門的代碼集來處理不同的工作輸出緩衝區更加高效。

這還允許您以更簡潔的方式爲重要情況進行性能優化,而不會降低基本代碼的可維護性。從理論上講,我確信使用模板代碼,具體類設計等的複雜組合,並獲得幾乎相同的運行時效率......但我通常並不願意以實現複雜的實施交易。

3

我想這是更多的答案不是你要找的,但在這裏不用...

SO充滿了人們所擔心的X,Y或Z的性能問題,那種擔心是猜測的一種形式。

如果你擔心某件事的表現,別擔心,找出

這裏是做什麼:

  1. 編寫程序

  2. Performance tune it

  3. 從經驗

這是什麼教我學習,我」我一遍又一遍地看到它,是這樣的:

  • 最佳實踐說不要過早優化

  • 最佳實踐說使用大量的數據結構類,具有多層抽象,最好的大型O算法,「信息隱藏」,具有事件驅動和通知式架構。

  • 性能調優揭示其中時間是怎麼回事,它是:舞動的通用性,使山出molehills的,調用函數沒有實現,他們需要多長時間&性能並且使用指數時間做這在多個層上。

  • 然後問這個問題:大O算法,事件和通知驅動架構等最佳實踐背後的原因是什麼?答案來了:除其他外,性能

因此,在某種程度上,最好的做法是告訴我們:優化過早。明白這點?它說「不要擔心表現」,它說「擔心表現」,並且它導致我們試圖成功的事情不會成功擔心。我們擔心的越多,違揹我們的判斷就越糟糕。

我的建設性建議是:按照上面的步驟1,2和3。這將教你如何使用最佳實踐適度,這將給你最好的全面的設計。

0

成員函數不會與對象一起復制。只有數據字段有助於對象的大小。