我想在
B
的地方建造A
。
struct A {
size_t x; // 8 bytes
int i; // 4 bytes
}; // padding 4 bytes
struct B {
size_t x; // 8 bytes
bool b; // 1 byte
}; // padding 7 bytes
int main() {
A a;
auto p = new(&a) B;
}
这段代码定义明确吗?
placement new
会触摸填充字节(例如将所有内容设置为零)还是将直接与b
字节一起工作?
例如,两个
A
结构是连续存储的(就在第一个 A::i
和第二个 A::x
之后)。如果 placement new
接触到填充,第二个 A
的数据将被损坏。
这里有几件事需要讨论。
首先,填充通常是未指定的,因此您不应该假设您知道填充是什么以及填充在哪里。主要限制是
T[N]
类型的数组的大小为N * sizeof(T)
,即没有“额外的数组填充”。这为您提供了一些最小的填充结果 T
。这意味着你的“第一个
A::i
之后接着第二个A::st
”无法完成;这不是你能决定的事情。
placement-new 可以重用现有的存储,主要要求是存储足够大并且适合目标类型。您可以使用
sizeof
和 alignof
静态断言这些内容。 placement-new 表达式的结果是目标对象(在示例中为 B
类型)被初始化(按照所选初始化语法的要求),这可能会写入 占用的任何和所有存储空间B
对象。根据上述要求,这些将完全包含在提供的存储中,或者您已经拥有 UB。
如果你想要整个数组
A[N]
为某些对象序列提供存储,那么原则上当然可以覆盖多个相邻A
对象的存储,但只要每个B
对象都是放置的-new-构造成一个特定的 A
对象,并且该对象提供足够的存储空间(如上所述),那么任何一个 B
对象都不会使任何不相关的底层 A
对象失效。