2012-03-13 42 views
0

類A(比方說)中,具有僅具有成員函數存儲器靜態函數VS成員函數

如果我創建類A的1000個實例作爲類只包含靜態所有靜態成員函數僅 B類(比方說)成員函數,即使有1個實例或1000個實例,內存也不會增加。

但是,對於B類。如果我創建了1000個實例,是否會增加內存(即使是最輕微的,可能是指向成員函數集的每個對象的指針)?

如果否,那麼編譯器如何保存特定對象的成員函數信息的跟蹤?

回答

4

對於初學者,您可能會嘗試輸出sizeof(A)sizeof(B)。但 幾件事情要記住:

  • 無論數量或類型的成員中,C++禁止一類 的大小爲0,所以靜態成員與否,A每個實例都將 採取一些記憶;和

  • 的非虛擬函數的解析做完全由編譯 時間,所以沒有必要編譯任何東西添加到 類的。 (虛擬函數通常會將一個指針的大小增加到該類,而不管您的類有多少個虛擬函數。)

4

是否會增加內存(即使是最輕微的,可能是指向成員函數集的每個對象的指針)?

NO。
非虛擬成員函數不會影響類的對象大小。
但是,虛擬成員函數的存在通常會增加類對象的大小。

注意,後者是純粹的實現具體的細節,但由於所有已知的編譯器實現了使用v-tablev-ptr虛擬機制,這是合理的假設,幾乎所有的編譯器會顯示添加v-ptr到的每一個對象的相同行爲多態類,從而按類似於v-ptr的大小增加類對象的大小。

+1

也許只有虛擬方法;) – 2012-03-13 11:32:04

+0

@VJovic:的確如此! – 2012-03-13 11:33:57

1

如果我們是只是談論成員函數,印記將是相同的。一個成員函數不會佔用更多的內存,它所包含的類實例化的次數越多(因爲this指針被傳遞給它)。只有類的數據成員纔會在每個類實例化時佔用更多的內存,因爲它們對於類的每個實例都是唯一的。

所以要回答你的第二個問題,它在調用類的非靜態成員函數時通過this指針的用戶保持「跟蹤」。

虛擬方法讓事情變得更復雜一些,但是你的問題並沒有涉及到這個特定的習慣用法。

0

在較低的級別,沒有對象,只是函數調用。隱含的this參數被傳遞給成員函數。當我們調用void B::f(){ mem1(); }時,編譯器將其視爲B::mem1(this)。因此,即使您擁有數百萬個B類對象,也會有一個函數mem1期待B類對象。

虛擬函數是不同的。他們從表中查找,但是,查找結果取決於[實際]類型this(在mem1(this)中),而不是由this指向的對象。

1

您可以使用sizeof函數來測試函數是否佔用類對象的內存。

class A{}; 
class B{ 
    void foo(){}; 
}; 
class C{ 
    static void foo(); 
}; 
class D{ 
    virtual void foo(); 
}; 
class E{ 
    virtual void foo1(); 
    virtual void foo2(); 
} 

sizeof(A)=1
sizeof(B)=1
sizeof(C)=1
sizeof(D)=4
sizeof(E)=4

一流ABC對象的內存是零。但是如果他們的記憶爲零,編譯將無法區分這些類。所以編譯加上char來區分這些類。所以:

sizeof(A)=1
sizeof(B)=1
sizeof(C)=1

所以,你可以看到成員函數和靜態成員函數不佔用memory.So他們不會增加內存。

但是如果class具有虛函數,它會添加4個字節,並且它只添加4個字節是否具有多少虛函數。因爲它只添加一個指向虛表的虛表,其中包含虛函數的點。

0

靜態成員函數和普通成員函數的區別很簡單。當調用正常成員函數ECX寄存器被設置爲類實例的 你可以看到一個附加

LEA ECX,INSTANCE_NAME [EBP]

如果deassemble

的部件的地址函數使用此寄存器訪問類 ,所以內存使用不會增加,但計算時間會增加