在以下示例中 structE繼承了 structsC并且D沒有其他資料成員:
struct A{};
struct B{};
struct C : A, B {};
struct D : A, B {};
struct E : C, D {};
int main() {
static_assert(sizeof(C) == 1);
static_assert(sizeof(D) == 1);
//static_assert(sizeof(E) == 2); // in Clang and GCC
static_assert(sizeof(E) == 3); //in MSVC
}
在所有的編譯器我已經測驗過,sizeof(C)==1并且sizeof(D)==1,只有在MSVCsizeof(E)==3所以超過其父母/成員的總結大小,演示:https://gcc.godbolt.org/z/aEK7rjKcW
實際上我希望找到sizeof(E) <= sizeof(C) sizeof(D)(在空基優化的情況下更少)。而且這里幾乎沒有任何填充,否則sizeof(E)就是 2 或 4。
中額外空格 ( sizeof(E)-sizeof(C)-sizeof(D) == 1)的目的是什么E?
uj5u.com熱心網友回復:
首先,由于填充和對齊,它可能大于子物件的總和。但是,您可能已經意識到這一點,這不是您要問的。
要確定您的情況的布局,您可以使用以下代碼列印所有子物件的偏移量(及其型別的大小):
static E x;
int main() {
E *e = &x;
C *c = e;
D *d = e;
A *ca = c, *da = d;
B *cb = c, *db = d;
#define OFF(p) printf(#p " %d %d\n", (int)((char*)p - (char*)e), (int)sizeof(*p))
OFF(e);
OFF(c);
OFF(ca);
OFF(cb);
OFF(d);
OFF(da);
OFF(db);
}
gcc/clang 的輸出是:
e 0 2
c 0 1
ca 0 1
cb 0 1
d 1 1
da 1 1
db 1 1
MSVC 的輸出是:
e 0 3
c 0 1
ca 0 1
cb 1 1
d 2 1
da 2 1
db 3 1
這表明 MSVC 實作 EBO 的方式與其他編譯器不同。特別是,它不是將A和放置B在 內的相同地址,而是放置在 內C的相同地址D(就像其他編譯器那樣),而是將它們放在不同的偏移量處。然后,即使sizeof(C) == 1,當它是子物件時,它也會為它分配完整的兩個位元組。這樣做很可能是為了避免從另一個子物件中cb混淆其他一些B,即使在這種情況下它不會成為問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/375365.html
