9

我的这个问题中,@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();
}

Ideone 的示例输出(我知道 UB 也可以是“看似正确的行为”)。
请注意,我没有在类之外调用析构函数,以不访问生命周期已结束的对象。另请注意,@DeadMG 表示直接调用析构函数是可以的,只要它为每个构造函数调用一次。

4

2 回答 2

8

如果它不与堆栈展开冲突,那就没问题了。

您销毁对象,然后通过指针重建它。如果您需要构造和销毁一个没有默认构造函数的对象数组,您会这样做。

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

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

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

于 2011-06-03T07:23:42.793 回答
0

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

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

(2) 如果派生类调用foo(). 这会是一个好的行为吗?例如

struct Y : X {};  // especially when there is virtual ~X()
int main ()
{
  Y y;
  y.foo();
}
于 2011-06-03T08:03:41.723 回答