簡體   English   中英

C++中對象是如何存儲在內存中的?

[英]How are objects stored in memory in C++?

C++中對象是如何存儲在內存中的?

對於常規課程,例如

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };

使用Object的指針作為數組可以如下訪問i1?

((Object*)&myObject)[0] === i1?

關於 SO 的其他問題似乎表明將結構轉換為指針將指向 POD 類型的第一個成員。 如果有構造函數的類,這有什么不同? 非 POD 類型又有什么不同?

編輯:

因此,在內存中,上面的類會像下面這樣排列嗎?

[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]

差不多。 您強制轉換為 Object*,而忽略了獲取地址。 讓我們重新提問如下:

((int*)&myObject)[0] == i1

你必須非常小心這樣的假設。 當您定義了結構時,這在您可能遇到的任何編譯器中都應該是正確的。 但是,正如其他人所說,對象的各種其他屬性(您可能在示例中省略了這些屬性)將使其成為非 POD,並且可能(可能以依賴於編譯器的方式)使上述陳述不成立。

請注意,如果您詢問 i3,我不會很快告訴您它會起作用——在這種情況下,即使對於普通的 POD,對齊或字節順序也很容易把您搞砸。

無論如何,如果可能的話,你應該避免這種事情。 即使它現在工作正常,如果你(或其他任何不明白你在做這個技巧的人)改變了結構順序或添加了新的字段,這個技巧在你使用過的所有地方都會失敗,這可能很難找到。

對您的編輯的回答:如果這是您的整個類定義,並且您正在使用具有默認選項的主流編譯器之一,並在 x86 處理器上運行,那么是的,您可能已經猜到了正確的內存布局。 但是編譯器的選擇、編譯器選項和不同的 CPU 架構很容易使您的假設無效。

沒有虛擬成員和繼承的類就像結構一樣在內存中布局。 但是,當您開始獲得繼承級別時,事情會變得棘手,並且很難弄清楚事物在內存中的順序(尤其是多重繼承)。

當您有虛擬成員時,它們在內存中有一個“vtable”,其中包含指向基於類的繼承層次結構創建的實際函數的指針。

底線是:如果可以避免的話,根本不要以這種方式訪問​​類(也不要對它們進行 memset 或 memcpy)。 如果您必須這樣做(為什么?),那么請注意您確切地知道您的類對象將如何在內存中,並小心避免繼承。

不同之處在於此技巧僅對 POD 類型有效。 這就是它的全部內容。 該標准指定此轉換對 POD 類型有效,但不保證非 POD 類型會發生什么。

這實際上取決於編譯器,或者更確切地說,由編譯器來確定內存布局。

例如,可以混合使用公共、私有和受保護的成員變量,以便每個訪問類型都是連續的。 或者,派生類的成員變量可能與超類中未使用的空間交錯。

虛擬繼承的情況變得更糟,虛擬繼承的基類可以放置在為該特定實例分配的內存中的任何位置

POD 不同,因為它需要與 C 兼容。

通常重要的不是類是否有構造函數:重要的是類是否有任何虛方法。 有關詳細信息,請谷歌搜索“vtable”和“vptr”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM