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

关于C++标准中数组新创建子对象的指针运算及对象重写有效性的技术问询

关于C++标准中数组新创建子对象的指针运算及对象重写有效性的技术问询

首先咱们把问题拆解清楚:你给出的这段代码里,核心疑问是foreign_function中标记为(*)的char* pointer5 = p_object4 + 6;这个指针算术操作是否符合C++标准,进而判断后续重写object3的操作是否有效。先贴出完整代码方便参考:

#include <iostream>

void foreign_function(short* s);

int main() {
    alignas(8) char object1[16];
    short* p_object2 = new(object1 + 2) short(10);  // 创建short类型的object2
    long* p_object3 = new(object1 + 8) long(100);   // 创建long类型的object3

    foreign_function(p_object2);
    std::cout << *p_object3  << std::endl;
}

void foreign_function(short* s) {
    char* p_object4 = new(s) char();  // 创建char类型的object4
    char* pointer5 = p_object4 + 6;   // (*) 核心疑问的指针算术操作
    new(pointer5) long(1000);  // 尝试透明替换原object3
}

接下来结合C++标准(N4861版本)的相关条款一步步分析:

一、梳理各对象的生命周期与存储关系

  • object1是alignas(8)修饰的char[16]数组,它的生命周期从main启动直到结束,全程未被整体销毁或重用,因此生命周期始终有效。
  • 用placement new创建object2(short类型)在object1+2位置时,根据[intro.object]第3段规则,object1为object2提供了存储,因此object1的生命周期不会终止,但object1中被object2覆盖的第2、3个char元素(对应索引2、3)的生命周期会结束(存储被重用,符合[basic.life]第1.5段)。
  • 同理,创建object3(long类型)在object1+8位置时,object1中对应索引8到11的char元素生命周期结束。
  • 进入foreign_function后,在s(即object2的地址)创建object4(char类型):此时object2的存储被重用,生命周期结束;而根据[intro.object]第2段规则,object4会成为object1的子对象——因为object1生命周期仍在,object4的存储完全在object1范围内,且类型与object1的元素类型一致(均为char)。

二、核心疑问:p_object4 + 6的指针算术是否合法?

这部分的关键是判断p_object4是否可被视为指向object1数组的一个元素的指针,因为[expr.add]第4.2段明确要求:只有当原始指针指向数组对象的某个元素时,指针算术的结果才能指向该数组的其他元素(或超出末尾一个位置),否则行为未定义。

根据[intro.object]第2段的规则,object4是object1的子对象,且类型与object1的元素类型完全一致,创建位置正好是object1原来的第2个元素(索引2)的位置。此时p_object4本质上就是指向object1数组索引2处元素的指针——虽然该位置原来的char元素生命周期已结束,但新创建的object4作为object1的子对象,完全承接了这个数组元素的“身份”。

p_object4 + 6的计算结果指向object1数组索引2+6=8处的元素,这个位置在object1的16个元素范围内(索引0-15),完全符合[expr.add]第4.2段的要求,因此这个指针算术操作是合法的。

三、重写object3的操作是否有效?

当用pointer5(指向object1+8)通过placement new创建新的long对象时:

  • 原object3的存储被重用,其生命周期根据[basic.life]第1.5段终止。
  • 新创建的long对象与原object3类型完全一致,存储完全重叠,且原object3类型非const、也不包含const成员或引用成员,符合[basic.life]第8段的“透明替换”规则。因此后续std::cout << *p_object3的操作是合法的,会输出新对象的值1000。

总结:你代码中的指针算术操作合法,重写object3的操作也完全符合当前C++标准的要求。

备注:内容来源于stack exchange,提问作者hogeegoh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 09:49:30