是`new(this)MyClass();`直接调用析构函数后的未定义行为?

时间:2011-06-03 07:16:32

标签: c++ this undefined-behavior placement-new

this question of mine中,@ DeadMG表示通过this指针重新初始化类是未定义的行为。标准中有没有提到它?

示例:

#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();
}

Example output at Ideone(我知道UB也可能是“看似正确的行为”) 请注意,我没有在类之外调用析构函数,因为没有访问生命周期结束的对象。还要注意,@ DeadMG说直接调用析构函数是可以的 - 因为它为每个构造函数调用一次。

2 个答案:

答案 0 :(得分:8)

如果它与堆栈展开没有冲突,那就没关系。

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

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

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

这方面特别是未定义的行为。

答案 1 :(得分:0)

除了@ sharptooth的回答。我只是想知道另外2个案例。至少他们值得一提。

(1)如果使用foo()分配的堆上的指针调用malloc()。构造函数被调用。它可以安全吗?

(2)如果派生类正在调用foo(),该怎么办?这会是一个好的行为吗? e.g。

struct Y : X {};  // especially when there is virtual ~X()
int main ()
{
  Y y;
  y.foo();
}