代码之家  ›  专栏  ›  技术社区  ›  Alexander S

调用placement new时填充是否重要?

  •  0
  • Alexander S  · 技术社区  · 1 年前

    我想建造 B 在的地方 A .

    struct A {
      size_t st;  // 8 bytes
      int i;      // 4 bytes
    };            // padding 4 bytes
    
    struct B {
      B* ap;   // 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::st ). 如果 放置新的 触摸填充,秒 A. 的数据将被损坏。

    1 回复  |  直到 1 年前
        1
  •  2
  •   Kerrek SB    1 年前

    这里有几件事要讨论。

    • 首先,填充通常是未指定的,所以你不应该假设你知道填充的内容和位置

      • 每个标量子对象都有一个必须遵守的大小和对齐方式,以及
      • 类型的数组 T[N] 具有大小 N * sizeof(T) ,即不存在“额外的数组填充”。这为您提供了一些最小的填充后果 T .
    • 这意味着你的“第一个之后” A::i 排名第二 A::st “做不到;这不是你可以决定的事情。

    • 新的放置可以重用现有的存储,主要要求存储足够大,并与目标类型适当对齐。您可以使用静态断言这些东西 sizeof alignof 。放置新表达式的结果是目标对象(类型为 B 在您的示例中)被初始化(根据所选初始化语法的请求),这可能会写入由 B 对象根据上述要求,这些将完全包含在提供的存储中,或者您已经拥有UB。

    • 如果你想要一个完整的数组 A[N] 要为某个对象序列提供存储,那么原则上当然可以覆盖多个相邻对象的存储 A 对象,但只要每个 B 对象是新构建到一个特定的位置 A. 对象,并且该对象提供了足够的存储(如上所述),则没有 B 对象将使任何不相关的底层无效 A. 物体。