You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用placement new时内存填充是否重要?相关代码合法性分析

关于Placement New填充字节与内存构造的问题解答

先看你给出的代码示例:

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;
  // auto p = new(std::launder(&a)) B;  // is a bit better
}

下面逐个解答你的问题:

1. 调用placement new时内存填充是否重要?

非常重要。填充字节的处理属于未定义行为,C++标准没有规定编译器如何处理这些字节。如果你的内存区域和其他有效对象存在重叠(比如你提到的两个A连续存储的场景),填充字节被修改的话会直接破坏相邻对象的数据,引发难以排查的bug。

2. 上述代码是否定义良好?

代码的构造操作基本合规,但有几个关键注意点:

  • 当用new(&a) B在A对象的内存上构造B后,原A对象a的生命周期立即结束,之后绝对不能再访问a,只能通过指针p访问新构造的B对象。
  • 注释里的std::launder确实更规范:原指针&a的静态类型是A*,而现在内存中实际是B对象,std::launder可以让指针正确关联到新的B对象,避免因类型不匹配导致的未定义行为。
  • 前提是A和B的内存大小相同(这里64位系统下都是16字节),如果B的大小超过A,会直接触发非法的内存越界访问。

3. placement new会修改填充字节还是仅操作B的成员字节?

C++标准对此没有任何规定,属于未定义行为。不同编译器的实现差异很大:

  • 部分编译器只会初始化B的成员对应的字节,填充字节保持原有状态;
  • 部分编译器可能会把整个B占用的内存(包括填充部分)清零,或者填充调试用的占位值(比如0xcdcdcdcd)。

你绝对不能假设填充字节会保持不变,也不能依赖填充字节的任何值。回到你说的连续存储A的场景:如果第一个A的填充字节刚好覆盖第二个A的x成员,一旦placement new修改了这些填充字节,第二个A的x就会被破坏,这种情况完全取决于编译器实现,没有任何保障。

内容的提问来源于stack exchange,提问作者Alexander S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:15:23