假设这样的结构:
A
超出了我们的控制范围,但我们可以更改B
结构:
struct A {
int64_t x; // 8 bytes
int32_t y; // 4 bytes
// 4 padding bytes
};
struct B {
A a; // 16 bytes
int32_t z; // 4 bytes
// 4 padding bytes (alignof(B) == alignof(A) == 8)
};
static_assert(sizeof(B) == 24); // 8 useless bytes!
有没有办法将
z
放入 A
填充(某些属性)?
填充的重用由 ABI 决定,而不是标准或编译器。例如,在 Linux 上这将起作用:
struct A {
int64_t x; // 8 bytes
int32_t y; // 4 bytes
// 4 padding bytes
A() = default; // <-- CHANGE HERE
};
struct B {
[[no_unique_address]] A a; // <-- CHANGE HERE
int32_t z; // 4 bytes in the padding of A
};
static_assert(sizeof(B) == 16);
A
需要符合其类型的某些属性才能有资格重复使用尾部填充。对于此 ABI,它需要“不是”C++03 中的 POD。添加用户声明的构造函数就足够了。
然后在B
内,我们需要诱导使用尾部填充。例如,如果
A
是基类,它将重用其尾部填充。或者,使用 [[no_unique_address]]
也能达到同样的效果。