是`new(this)MyClass();`直接调用析构函数后的未定义行为? [英] Is `new (this) MyClass();` undefined behaviour after directly calling the destructor?

查看:102
本文介绍了是`new(this)MyClass();`直接调用析构函数后的未定义行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的这个问题中,@ DeadMG说通过这个指针重新初始化一个类是未定义的行为。

In this question of mine, @DeadMG says that reinitializing a class through the this pointer is undefined behaviour. Is there any mentioning thereof in the standard somewhere?

例如:

#include <iostream>

class X{
  int _i;
public:  
  X() : _i(0) { std::cout << "X()\n"; }
  X(int i) : _i(i) { std::cout << "X(int)\n"; }

  ~X(){ std::cout << "~X()\n"; }

  void foo(){
    this->~X();
    new (this) X(5);
  }

  void print_i(){
    std::cout << _i << "\n";
  }
};

int main(){
  X x;
  x.foo();
  // mock random stack noise
  int noise[20];
  x.print_i();
}

示例输出在Ideone (我知道UB也可以是看似正确的行为)。

请注意,我没有调用类外的析构函数,因为不访问一个对象生命已经结束。还要注意,@DeadMG说直接调用析构函数是一样好,因为它为每个构造函数调用一次。

Example output at Ideone (I know that UB can also be "seemingly correct behaviour").
Note that I did not call the destructor outside of the class, as to not access an object whose lifetime has ended. Also note, that @DeadMG says that directly calling the destructor is okay as-long-as it's called once for every constructor.

推荐答案

你销毁对象,然后通过指针重建它。如果你需要构造和销毁没有默认构造函数的对象数组,那么你可以这么做。

You destroy the object, then reconstruct it via the pointer. That's what you would do if you needed to construct and destroy an array of objects that don't have a default constructor.

问题是这是异常不安全。如果调用构造函数抛出异常并且堆栈被解开并且析构函数第二次被调用,该怎么办?

The problem is this is exception unsafe. What if calling the constructor throws an exception and stack is unwound and the destructor is called for the second time?

{
   X x;
   x.foo(); // here ~X succeeds, then construction fails
} //then the destructor is invoked for the second time.

这方面具体是未定义的行为。

That aspect specifically would be undefined behavior.

这篇关于是`new(this)MyClass();`直接调用析构函数后的未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆