调用新展示位置时,填充重要吗?

问题描述 投票:0回答:1

我想在

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
的数据将被损坏。

c++ padding placement-new
1个回答
2
投票

这里有几件事需要讨论。

  • 首先,填充通常是未指定的,因此您不应该假设您知道填充是什么以及填充在哪里。主要限制是

    • 每个标量子对象都有一个必须遵守的大小和对齐方式,并且
    • 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
    对象失效。

© www.soinside.com 2019 - 2024. All rights reserved.