2014-03-01 33 views
3

這裏是一個簡單的C++類:類成員和成員函數的內存位置

class A 
{ 
public: 
    explicit A() : m_a(0) { } 
    explicit A(int a) m_a(a) { } 
    int getA() const { return m_a; } 
    void setA(int a) { m_a = a; } 

private: 
    int m_a; 
} 

這是我目前所知:

  • 當你聲明一個類的實例的對象,內存獲取分配給該對象。分配的內存相當於其成員的內存總結。所以,在我的情況sizeof(A) = sizeof(int) = sizeof(m_a)
  • A類的所有成員函數某處存儲在內存和A類的所有實例使用相同的成員函數。

這是我知道:

在哪裏存儲成員函數和它們是如何實際存儲?假設一個int例如存儲在4個字節上;我可以想象RAM存儲器佈局與4個連續的單元格,每個單元格存儲一部分int。我怎麼能想象這個佈局的功能?(這聽起來可能很愚蠢,但我認爲函數必須在內存中佔有一席之地,因爲你可以有一個指針指向它們)。還有如何以及在哪裏存儲功能指令?我的第一個看法是函數和函數指令存儲在程序可執行文件(及其動態或靜態庫)中,但是如果這是真的,那麼創建函數指針時會發生什麼? AFAIK函數指針指向RAM內存中的位置,它們可以指向程序二進制文件中的位置嗎?如果是的話,這是如何工作的?

任何人都可以向我解釋如何工作的,如果我知道什麼是對錯指出?

+1

嗯,你不能執行不首先加載到RAM代碼... – molbdnilo

+0

指針不指向內存,但虛擬內存。 –

回答

10

首先,你需要了解linker的角色和什麼executables(在virtual memory通常執行)和address spaces & processes。在Linux上,閱讀有關ELFexecve(2)系統調用。另請參閱Levine's Linkers & Loaders book

成員函數可以是虛擬的或純函數。

  • 一個普通的(非virtual)成員函數就像一個C函數(除了其具有this作爲隱式的,通常首先,參數)。例如您的getA方法類似於下面的C函數實現(對象的外面,例如在二進制可執行文件的code segment):

    int C$getA(A*thisptr) const { return thisptr->m_a; } 
    

    然後想象編譯器翻譯p->getA()C$getA(p)

  • A virtual member function通常通過vtablevirtual method table)實施。具有一些虛擬成員函數(包括析構函數)的對象通常作爲其第一個(隱式)成員字段指向這樣一個表(由編譯器在別處生成)的指針。您class A沒有任何虛方法,但想象一下,如果它有一個額外的virtual void print(std::ostream&);方法,那麼你的class A將具有相同的佈局

    struct A$ { 
        struct A$virtualmethodtable* _vptr; 
        int m_a; 
    }; 
    

    和虛擬表可能是

    struct A$virtualmethodtable { 
        void (*print$fun) (struct A$*, std::ostream*); 
    }; 
    

    (因此添加其他虛擬功能意味着只需在該vtable)中添加插槽; 然後像p->print(std::cout);呼叫將被翻譯幾乎像 p->_vptr.print$fun(p,&std::cout); ... ...此外,編譯器會生成作爲恆定表各種虛擬方法表(每類中的一個)。

注意:事情比較複雜,多重或虛擬繼承。

在兩種情況下,成員函數不吃在對象中的任何額外的空間。如果它是非虛擬的,它只是一個普通的函數(在代碼段中)。如果它是虛擬的,它在虛擬方法表中共享一個插槽。

注意:如果您使用最近的GCC進行編譯(即使用g++),您可以通過例如-fdump-tree-all標誌:它將產生數百個轉儲文件,在轉儲的文本格式中部分顯示 - 編譯器的一些內部表示,您可以使用尋呼機(例如less)或文本編輯器進行檢查。您也可以使用MELT或查看使用g++ -S -fverbose-asm -O1生成的彙編代碼....

+1

很好的答案,我不能相信它有這麼幾個票! –

-2

要理解這一點,您需要了解程序的內存佈局。代碼將被對象共享。所有對象都將擁有自己的數據副本。

+0

從那裏我可以學到一些資源會有很大的用途 –

+1

[鏈接](http://stackoverflow.com/questions/1632600/memory-layout-c-objects),並瞭解代碼和數據段可以讀取內存佈局c/C++程序http://www.cs.uwm.edu/classes/cs315/Bacon/Lecture/HTML/ch10s04.html – LearningC