2017-04-20 44 views
0

我想努力去理解在主程序中聲明的變量和實例化的類對象內的變量之間的內存尋址差異的概念!在C++中的「類實例化對象和變量內的對象地址」的內存地址

我的問題是當我在主程序中聲明兩個變量例如「int a,int b」時,它需要4 + 4字節,並且在內存中有一個特定的兩個地址。例如「a在內存0x248444和b在0x248448」....在這種情況下很好....

當涉及到具有兩個變量「int c,int d」的類實例化對象時,對象需要一個8字節的例子「0x248544」的內存地址,那麼「int c和int d」的地址呢?

因此int c和int d的地址在對象地址「0x248544」之內? int c和int d是否有特定的地址?

如何理解實例化的類對象地址與該對象內部變量的地址之間的區別?

希望我的問題是明確....

在網上搜索後,我發現了一本書,叫「C++對象模型中」,但關於在實例化類對象中聲明的變量存儲差別基本認識並在main中聲明變量。有人請幫我明確自己。

在此先感謝。

+0

內存佈局取決於平臺。例如,成員之間的填充取決於特定平臺上成員類型的大小和對齊要求。我不確定最新的標準,但我知道一段時間成員訂單隻保留給具有相同訪問說明符的成員。 –

+0

related/dupe:http://stackoverflow.com/questions/26939609/how-is-the-memory-layout-of-a-class-vs-a-struct – NathanOliver

+0

如果它是POD,則類對象與struct的佈局相同(包括填充)。該變量的地址很可能與類本身有一些偏移。可以使用'offsetof(cls,some_var)' – Brandon

回答

2

好吧,你有一個C級這樣的:

class C 
{ 
    int c; 
    int d; 
}; 

C類(C c)的實例會佔用一些內存,它需要(提供int是4個字節大 - 這是不一定的情況下在所有機器上,雖然)8個字節。

如果一個實例位於地址0x248544,它將佔用該地址+下一個地址的字節。在上述這樣一個簡單的類中,沒有任何進一步的條件,c將佔據這八個字節中的前四個字節,d接下來的四個字節。

所以c.c與您的對象c的地址完全相同,並且c.d位於四個字節之後,因此將具有地址0x248548。

請注意,雖然第一個成員不一定具有與您的對象相同的地址!讓我們修改我們的C類:(!)

class C 
{ 
    virtual ~C() { } // virtual destructor -> C gets virtual! 
    int c; 
    int d; 
}; 

現在的sizeof(C)將是16(提供指針需要8個字節存儲,現代64位硬件)。爲什麼?該類獲得一個指向vtable的附加指針,通常是類C的第一個(但不可見)成員。

因此c仍然位於地址0x248544,但現在指向vtable的(不可見的)指針共享此地址; c.c後來,因此位於地址0x2484c和c.d然後位於0x24850。

在這方面,C++是從C,其中一個結構的第一構件總是共享結構本身的地址不同...

無論是在C和C++,雖然,兩個後續成員不一定必須「互相觸摸」,可能會在一段關鍵字字節對齊之間填充一些字節。

此外,C++允許以重新排序類的成員: 而在C中,如果結構構件ab之前聲明,那麼a必須放置在在存儲器b前,太,這是C++,才需要爲同一個可訪問性的成員!

class C 
{ 
    int a; 
public: 
    int b; 
private: 
    int c; 
}; 

編譯器現在被允許離開訂單不變,但它可能也將b的前面或其他兩個後 - 只有a不允許放置c後。

長的故事,簡短的結論:所有這一切的內存佈局的東西複雜得多可能比你希望它是...

邊注到虛函數表:V表指針不要求有(就到C++標準) - 如果任何編譯器供應商發現更好的解決方案來實現多態,他們可以自由地這樣做 - 如果他們發現...但vtable是目前的藝術狀態,一種事實上的標準。

+0

很好解釋!正是我期待的! 非常感謝 – Macs

1

您可以將類實例視爲其成員變量的包絡。類實例的大小是其成員變量的大小加上它們之間的可選填充的總和。通常(繼承和多態可以混淆這個)第一個成員變量的地址與類實例的地址相同。您可以獲取成員的地址並在調試器中對其進行調查,以瞭解其工作原理。例如。通過c佔據

class C 
{ 
public: 
    int a = 1; 
    int b = 2; 
}; 

C c; 
int* p_a = &c.a; 
int* p_b = &c.b; 

檢查內存,您將看到價值12內。

成員變量的順序被保留下來,並可能因爲填充而影響類實例的大小。

一個空的類的實例必須有一個地址,因此它的大小是從來沒有0

成員函數是一個不同的故事。雖然它們也位於內存中,但它們由所有實例共享,因此存儲在一個地方,與實例分開。

+0

感謝您的及時回覆 – Macs