【发布时间】:2011-09-07 14:57:05
【问题描述】:
在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 表示直接调用析构函数是可以的,只要它为每个构造函数调用一次。
【问题讨论】:
-
这种结构(调用析构函数,然后调用带有放置 new 的构造函数)是实现赋值运算符的一种流行方式,直到发现异常不安全。我不记得有人说它是UB,没有例外。可能有虚函数和多重继承的情况是UB。
-
如果是UB,那只是因为使用了
this。如果是这种情况,您仍然可以通过在调用析构函数之前获取this的副本来解决它。 -
+1 程序员。事实上,C++0x 标准 (FDIS) 包含手动销毁 + 放置构造的示例,因此它可能没有那么糟糕。当某些成员具有非平凡的构造函数/析构函数时,它在 §9.5/4 中作为更改联合的 active 成员的方法:
u.m.~M(); new (&u.n) N;现在,示例不会从inside 一个方法,但我不知道这是否有任何区别。 -
@curiousguy 指向存储的指针将保持有效。我在猜测是否有关于使用
this作为关键字的规则,而不是它的特定值。也就是说,我在考虑之前是否可以访问该值(由于其他要求,这显然是正确的),是否允许使用this? -
@LucDanton
this只是一个关键字,用于获取非静态成员函数的隐式参数的值。即使在从未使用过this->~T();、delete this;或new (this) T;的程序中,this也可以引用尚未完全构造的对象,在某些情况下,例如甚至没有开始子对象构造。
标签: c++ this undefined-behavior placement-new