3 回答

TA貢獻1876條經驗 獲得超7個贊
您可以將標準布局類對象地址強制轉換為指向其第一個成員的指針,并通過后面的段落將其返回,這通常也可以在C語言中完成:
struct A { int x; };
A a;
// "px" is guaranteed to point to a.x
int *px = (int*) &a;
// guaranteed to point to a
A *pa = (A*)px;
為此,第一個成員和complete對象必須具有相同的地址(編譯器無法通過任何字節調整int指針,因為它無法知道它是否是int的成員A)。
最后,如果一個以上的構成類具有數據成員,那會出什么問題?
在一個類中,成員根據聲明順序以遞增地址分配。但是,C ++并未規定跨類的數據成員的分配順序。如果派生類和基類都具有數據成員,則Standard不會故意為其地址定義順序,以便在內存布局方面為實現提供完全的靈活性。但是,要使上述演員表正常工作,您需要知道分配順序中的“第一個”成員是什么!
如果第一個數據成員也是基類,怎么辦?
如果基類與第一個數據成員具有相同的類型,則將基類放在內存中派生類對象之前的實現將需要在內存中派生類對象數據成員之前具有填充字節(基類的大小為1 ),以避免對基類和第一個數據成員使用相同的地址(在C ++中,相同類型的兩個不同對象始終具有不同的地址)。但是,這將再次使得無法將派生類對象的地址轉換為其第一個數據成員的類型。

TA貢獻1906條經驗 獲得超10個贊
基本上是關于與C ++ 03和C的兼容性:
相同的訪問控制-允許C ++ 03實現使用訪問控制說明符作為對類的(組)成員重新排序的機會,例如為了更好地打包它。
層次結構中有多個具有非靜態數據成員的類-C ++ 03沒有說基類位于何處,也沒有說明填充是否會存在于同類型的完整對象中的基類子對象中。
基類和相同類型的第一個成員-由于第二條規則,如果基類類型用于數據成員,則它必須是空類。許多編譯器確實實現了空基類優化,因此Andreas關于具有相同地址的子對象的說法是正確的。我不確定標準布局類的含義是什么,這意味著基類子對象具有與相同類型的第一個數據成員相同的地址是不好的,但是基類子對象何時具有與不同類型的第一個數據成員相同的地址。[編輯:這是因為相同類型的不同對象具有不同的地址,即使它們是空的子對象也是如此。感謝約翰內斯]
的C ++ 0x大概可以有定義的那些東西都是標準布局類型也是如此,在這種情況下,它也將確定他們是如何布局,以它為標準布局類型相同的程度。Johannes的回答更進一步,請看他的示例,這些示例會干擾標準布局類的良好屬性。
但是,如果這樣做,則某些實現將被迫更改它們對類的布局方式,以適應新的要求,這對于C ++ 0x前后的不同版本的編譯器之間的結構兼容性造成了麻煩?;旧?,它破壞了C ++ ABI。
我對如何定義標準布局的理解是,他們著眼于在不破壞現有實現的情況下可以放寬哪些POD要求。因此,我假設不做任何檢查,以上是一些現有的C ++ 03實現確實使用類的非POD性質來執行與標準布局不兼容的示例。

TA貢獻1765條經驗 獲得超5個贊
如果我們允許數據成員具有不同的訪問控制,那會出什么問題?
當前的語言表示,編譯器無法在相同的訪問控制下對成員重新排序。喜歡:
struct x
{
public:
int x;
int y;
private:
int z;
};
這里x必須在y之前分配,但是相對于x和y對z沒有限制。
struct y
{
public:
int x;
public:
int y;
};
新的措辭說,y盡管有兩個publicS,但仍是POD 。這實際上是放寬規則。
- 3 回答
- 0 關注
- 650 瀏覽
添加回答
舉報