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

placement new复用存储后C++数组的生存期及操作合法性问题

关于placement new复用数组存储的生存期与操作合法性问题

这是此前某问题及其回答的后续内容。

#include <new>

struct A {
    int x{42};
    int y{24};
};
static_assert(sizeof(A) == 2 * sizeof(int));
static_assert(alignof(A) == alignof(int));
int main() {
    int storage[5] = {0, 1, 2, 3, 4};
    ::new (static_cast<void *>(storage + 1)) A;
    // storage及其子对象的生存期状态如何?
    // 指针算术是否仍然有效?

    return *(storage + 4);  // 这一操作是否合法?
}

可在线编译运行验证。


核心问题

  • 通过placement new复用storage数组的部分存储后,原数组storage是否仍处于生存期?
  • 指针算术与解引用操作是否合法?
  • 若多次复用同一存储位置,情况又如何?

C++标准中“提供存储”的规则仅将std::byte和unsigned char数组列为可提供存储的例外情况,因此对其他类型数组的行为存在疑问。

另外,关于被A覆盖部分的解引用,此前的回答中用到“可透明替换”的概念做了论证;但如果把A替换为double(暂不考虑对齐问题),该概念就不再适用。


问题解答

1. 原数组storage的生存期状态

原数组storage的未被覆盖部分(storage[0]、storage[3]、storage[4])仍处于正常生存期,但被A对象覆盖的storage[1]和storage[2]这两个int元素的生存期已终止。

根据C++对象生存期规则:当在已有对象的存储位置上创建新对象时,若新对象类型与原对象类型不完全一致,原对象的生存期会被立即终止。数组作为整体,只要其存储未被完全覆盖,未被触及的元素仍保持有效。

2. 指针算术与解引用的合法性

  • 未被覆盖区域的操作:*(storage + 4)(即storage[4])的操作完全合法。该元素未被placement new覆盖,生存期正常,指针算术基于原数组的int类型进行,符合数组指针算术规则,解引用直接指向有效的int对象。
  • 被覆盖区域的操作:若仍以int*类型对storage +1到storage +2的位置做解引用,会触发未定义行为——因为原int对象已消亡,当前存储的是A对象,类型不匹配。但如果通过A*类型访问(比如auto a_ptr = reinterpret_cast<A*>(storage + 1);),则完全合法,因为A对象正处于生存期。
  • 数组整体的指针算术:从storage出发做不超过原数组存储范围的指针算术(比如storage +3)本身是合法的(指针允许指向数组末尾之后一个位置),但解引用未被覆盖且有效的元素之外的位置(比如storage[1])则不合法。

3. 多次复用同一存储位置的情况

如果多次在同一存储位置用placement new创建对象:

  • 若原对象具有非平凡析构函数,每次创建新对象前必须手动调用原对象的析构函数,否则会导致资源泄漏或未定义行为。
  • 每次新对象创建后,原对象的生存期立即终止,新对象接管存储位置。若新对象类型与之前的类型不同,后续访问必须匹配当前对象的类型,否则触发未定义行为。
  • 若多次创建的是相同类型的平凡对象,且存储布局兼容,满足“可透明替换”条件,理论上可以通过原类型的指针/引用访问新对象,但仍建议显式管理生存期,避免依赖标准灰色区域的行为。

关于“可透明替换”的补充说明

对于struct A和int数组元素的场景,A的大小、对齐与两个int完全一致,且A是平凡类型,符合“可透明替换”的条件——因此此前的回答中可以论证通过int*读取A::x这类操作在某些场景下可被接受,但这属于标准未明确规定的灰色区域,生产代码中不建议依赖。而如果替换成double,由于double与int类型不兼容、存储布局不匹配,“可透明替换”完全不适用,任何通过int*访问该存储位置的操作都是未定义行为。


内容的提问来源于Stack Exchange,提问作者Oersted

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 04:23:14