好吧,你有一個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中,如果結構構件a
被b
之前聲明,那麼a
必須放置在在存儲器b
前,太,這是C++,才需要爲同一個可訪問性的成員!
class C
{
int a;
public:
int b;
private:
int c;
};
編譯器現在被允許離開訂單不變,但它可能也將b
的前面或其他兩個後 - 只有a
不允許放置c
後。
長的故事,簡短的結論:所有這一切的內存佈局的東西複雜得多可能比你希望它是...
邊注到虛函數表:V表指針不要求有(就到C++標準) - 如果任何編譯器供應商發現更好的解決方案來實現多態,他們可以自由地這樣做 - 如果他們發現...但vtable是目前的藝術狀態,一種事實上的標準。
內存佈局取決於平臺。例如,成員之間的填充取決於特定平臺上成員類型的大小和對齊要求。我不確定最新的標準,但我知道一段時間成員訂單隻保留給具有相同訪問說明符的成員。 –
related/dupe:http://stackoverflow.com/questions/26939609/how-is-the-memory-layout-of-a-class-vs-a-struct – NathanOliver
如果它是POD,則類對象與struct的佈局相同(包括填充)。該變量的地址很可能與類本身有一些偏移。可以使用'offsetof(cls,some_var)' – Brandon