【发布时间】:2014-10-28 17:28:46
【问题描述】:
#include <cstdlib>
struct B {
virtual void f();
void mutate();
virtual ~B();
};
struct D1 : B { void f(); };
struct D2 : B { void f(); };
void B::mutate() {
new (this) D2; // reuses storage — ends the lifetime of *this
f(); // undefined behavior - WHY????
... = this; // OK, this points to valid memory
}
我需要解释一下为什么f() 调用有UB? new (this) D2; 重用存储,但它也为D2 调用构造函数,并开始新对象的生命周期。在这种情况下,f() 等于 this -> f()。 那就是我们只是调用D2的成员函数f()。谁知道为什么是UB?
【问题讨论】:
-
Placement-new 应该用于大多数派生类,并用相同类型的对象替换它们。这是您拥有 UB 的另一个原因,因为您不仅要替换基类子对象,还要用不同类型的对象替换它。
-
@0x499602D2 18.6.1.3 标准定义了这种放置新的行为,但没有说明应该在大多数派生类上使用 ,并创建相同类型的对象。
-
3.8 "如果在对象的生命周期结束后 […],在原始对象占用的存储位置创建一个新对象,[…] 原始对象的名称 [… ] 将自动引用新对象 […] 并可用于操作新对象 […] 如果:原始对象是类型 T 的最衍生对象 (1.8) 并且新对象是类型最衍生的对象T(也就是说,它们不是基类子对象)。”
-
@St.Antario:标准规定“程序可以通过重用对象占用的存储空间或通过显式调用对象的析构函数来结束任何对象的生命周期具有非平凡析构函数的类类型。”在重用其内存之前,对象是否还活着并不重要。后来肯定不是。
-
@St.Antario:调用析构函数足以结束对象的生命周期,但不是必需的。
标签: c++ class inheritance struct