2008-11-14 53 views
9

C++標準規定單個訪問節中的成員變量必須按照它們聲明的順序排列在內存中。同時,編譯器可以自由選擇訪問節本身的相互順序。這種自由使理論上不可能鏈接由不同編譯器創建的二進制文件。那麼嚴格的內部排序的剩餘原因是什麼?並且即將推出的C++ 09新的C++ 11標準提供了一種「手工」完全確定對象佈局的方法嗎?C++中的類佈局:爲什麼會員有時會訂購?

+0

C++ 11修訂此澄清,介入_repeated_訪問修飾符(無論何種原因,有人可能會包括那些)不妨礙佈局保證;只有當訪問級別通過_different_說明符更改時,纔會重複前一個。 – 2016-02-10 12:12:41

回答

8

這種自由使理論上不可能鏈接由不同編譯器創建的二進制文件。

由於諸多原因,結構佈局最不重要。的operator newdelete,數據類型大小虛函數表,實現...

那麼,什麼是嚴格的截面訂貨剩餘原因是什麼?

C兼容性,我會想到,這樣在C中定義的結構體包它在C++ 以同樣的方式對一個給定的編譯器設置

標準提供了一種「手工」完全確定對象佈局的方法嗎?

不,不超過現行標準。

對於classstruct沒有vtable和完全私人(或公共)字段,但是,如果您使用[u]int[8|16|32|64]_t類型,則已可能。你有什麼使用情況比這更多?

+0

>你有什麼使用情況比這更多? 優化。通過重新排序數據成員,可以使對象變小。代碼中的順序通常反映了邏輯組的成員,所以你不想改變它。 – 2008-11-14 13:37:22

0

編輯:我怕我誤解你的問題

我認爲這對內存訪問的優化。 例如,如果我們有這樣的結構:

struct example 
{ 
    int16 intData; 
    byte byteData; 
    int32 intData; 
    byte intData; 
    int32 intData; 
} 

讓我們假設在這個平臺上的字都是32位。然後,你將需要4個完整的單詞來通過在結構中的所有數據:

INT16 +字節= 24位(NETX場不適合在這裏)

INT32 = 32位(NETX場不適合在這裏)

字節= 8個比特(NETX場不適合在這裏)

INT32 = 32位

但是,如果重新排列場s到:

struct example 
{ 
    int16 intData; 
    byte byteData; 
    byte intData; 
    int32 intData; 
    int32 intData; 
} 

然後你可以保存一個內存訪問。

2

[編輯] 我今天新學到了一些東西!發現了以下標準報價:

一個 (非聯合)類的非靜態數據成員聲明沒有 居間訪問說明符被分配 這樣以後構件具有類 對象內 高地址。的由 訪問說明符分離 非靜態數據成員分配的順序是不確定的 (11.1)。執行對齊 要求可能會導致兩個相鄰的 成員不會立即被分配到 之後;因此可能需要 來管理虛擬功能(10.3)和虛擬 基類(10.1)。

有趣的 - 我不知道爲什麼這種自由度給出。繼續TH我以前的答覆的休息...


如前所述,對於維護訂購的原因是C兼容性,那時候我想的重新排序成員的利益沒有人想到,在內存佈局是典型的做法無論如何。另外,現在被認爲是「醜陋的技巧」(比如使用memset將選定的成員歸零,或者具有兩個具有相同佈局的結構)是相當普遍的。

該標準不給你一個方法來強制執行給定的佈局,但大多數編譯器提供的措施來控制填充,例如MSVC編譯器上的#pragma包。

其原因自動填充是平臺的可移植性:不同的體系結構有不同的對齊要求,例如有些體系結構會導致錯誤的整數(這是當時的簡單情況)。

+0

Nah,我很確定他是對的。我無法查閱這裏的標準來查看它,但我之前也注意到了這一點。它說,不同訪問節之間的順序是未指定的,但是在一節中,成員按聲明的順序排列。我也想知道點是什麼 – jalf 2008-11-14 11:22:31

0

您不應該鏈接由不同編譯器創建的對象。即使您所談論的內容發生了變化,您仍然會遇到更多問題,導致您無法與其他編譯器生成的文件進行鏈接。 (對齊,命名修改,調用約定只命名其中的幾個)。

一個原因編譯器可以自由訂購訪問欄目周圍可能是這樣的編譯器可以建立在接入部分的順序爲:低地址成員比更高地址的成員更受保護,例如。

如果不允許重新排序,你不會得到任何東西:只有莢提供C兼容性和辦法給你一個字節類/結構內成員的偏移量(使用宏offsetof),或者讓你memcpy的他們。如果您定義了自定義構造函數,複製構造函數,私有成員或其他內容,類型將變爲非POD。特別是,從一個類派生出來的當前打破了PODness。

C++ 1x降低了對POD的要求。例如,在C++中,1x std::pair<T, U>實際上是一個POD,儘管它提供了自己的構造函數(但必須符合某些規則)。

相關問題