用另一个对象重用对象的空间

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (3)

我希望从这个指针重用基类中的已分配空间,并且C ++ Standart不同意。但是,该标准的措辞似乎是错误的。它提出了一个条件“并且在对象占用的存储空间被重用或释放之前”,但它显然在它们自己的代码片段中被重用。哪里弄错了?

void B::mutate() {
  new (this) D2;    // reuses storage — ends the lifetime of *this!! REUSED AS WELL SO CONDITION SO RESTRICTIONS DON'T HOLD ANYMORE!
  f();              // undefined behavior

在对象的生命周期开始之前,但是在对象将占用的存储之后已经分配了41,或者在对象的生命周期结束之后,在对象占用的存储被重用或释放之前,任何表示对象的地址的指针可以使用对象将位于或位于的存储位置,但仅限于有限的方式。对于正在构建或销毁的对象,请参阅[class.cdtor]。否则,这样的指针指的是已分配的存储([basic.stc.dynamic.deallocation]),并且使用指针就像指针的类型为void *一样,是明确定义的。允许通过这样的指针的间接,但是得到的左值可以仅以有限的方式使用,如下所述。如果出现以下情况,该程 (6.1)对象将是或具有非平凡析构函数的类类型,并且指针用作delete-expression的操作数, (6.2)指针用于访问非静态数据成员或调用对象的非静态成员函数,或 (6.3)指针被隐式转换([conv.ptr])到指向虚拟基类的指针,或 (6.4)指针用作static_cast的操作数,除非转换是指向cv void的指针,或指向cv void的指针,随后指向cv char,cv unsigned char或cv std :: byte([cstddef.syn]),或 (6.5)指针用作dynamic_cast的操作数。 [例如: #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** ... = this; // OK, this points to valid memory } void g() { void* p = std::malloc(sizeof(D1) + sizeof(D2)); B* pb = new (p) D1; pb->mutate(); *pb; // OK: pb points to valid memory void* q = pb; // OK: pb points to valid memory pb->f(); // undefined behavior, lifetime of *pb has ended }

提问于
用户回答回答于

但它显然在他们自己的代码片段中重用。 new (this) D2; // reuses storage — ends the lifetime of *this f(); // undefined behavior** ... = this; // OK, this points to valid memory

正确。由于stoarge已被重用,因此“其他”条款适用:

...否则,这样的指针指的是已分配的存储([basic.stc.dynamic.deallocation]),并且使用指针就好像指针的类型为void *一样,是明确定义的。

f()通过a 调用void*是不可能的,因此该子句不允许。否则,调用生命周期结束的对象的成员函数是未定义的(在析构函数之外)。

... = this;另一方面一些可以用做void*

请注意,这(new (this) D2)->f()将是明确定义的。

用户回答回答于

当你这样做

f();

在一个成员函数中,你真正在做的是

this->f();

所以在他们这样做的例子中

new (this) D2; 

它结束了事物指针的生命周期,thisD2在它的位置创建了一个新的。这让你认为这this->f();是可以的,因为this现在指向一个已经开始生命的对象,但是你忘记了这this是一个指向一个已经终止它的对象的指针。您不能使用它来引用您创建的新对象。

为了能够f()合法地调用您需要做的是捕获返回的指针new并使用它来访问新对象

void B::mutate() {
  auto np = new (this) D2;    // reuses storage — ends the lifetime of *this
  f();              // undefined behavior**
  np->f()           // OK, np points to a valid object
  ... = this;       // OK, this points to valid memory
}

扫码关注云+社区

领取腾讯云代金券