C++标准是否允许用placement new将this替换为其他类型对象?
关于placement new替换
this指向对象的C++标准合规性 首先直接给结论:在满足特定前提条件的情况下,你示例中的操作是符合C++标准的,下面我会拆解细节和需要注意的边界:
核心规则依据
C++标准中关于对象生命周期的规则明确允许:在一个已存在对象的存储位置上,通过placement new构造另一个对象,只要满足以下要求:
- 新对象的存储大小不超过原对象占据的内存大小(你的示例里用
static_assert(sizeof(A) == sizeof(Derived))保证了这一点) - 新对象的对齐要求不超过原内存的对齐能力(示例里没显式检查,但如果
Derived的对齐需求比A严格,即使大小相等也会是未定义行为) - 原对象的类型不是const-qualified、volatile-qualified的,也不是引用类型(示例里的
A是普通非const类,符合要求)
当你执行new(this) Derived时,原A对象的生命周期会立即终止,新的Derived对象在同一块内存上开始生命周期——这完全符合标准规定。
关于this指针的后续使用
在placement new执行后,原this指针(类型为A*)现在指向的是一个Derived对象,这也是合法的:因为Derived是A的公有派生类(假设是公有继承,示例里没写但通常是这类场景),派生类对象可以被基类指针合法指向。
不过要注意:如果foo函数在placement new之后还有代码,那后续使用this时,访问的其实是新的Derived对象的成员。比如如果Derived重写了其他虚函数,此时调用那些函数会触发Derived的实现——这也是编译器无法对这类虚函数调用做去虚拟化优化的核心原因:编译器无法预判在虚函数执行过程中,对象的动态类型是否会被替换。
需要警惕的未定义行为场景
如果违反以下任一条件,你的代码就会触发未定义行为:
Derived的大小超过A的大小(示例里的static_assert已经避免了这一点)Derived的对齐要求比A更严格(比如A是按4字节对齐,Derived因为有某个成员要求8字节对齐)- 原
A对象是const类型(比如const A对象,你不能在其内存上构造新对象) - 继承是非公有的(此时基类指针
A*无法合法指向私有/保护派生的Derived对象)
内容的提问来源于stack exchange,提问作者king_nak
相关产品推荐
相关产品推荐

