当我执行这段代码时实际发生了什么?
class MyClass
{
MyClass()
{
//do something
delete this;
}
}
当我执行这段代码时实际发生了什么?
class MyClass
{
MyClass()
{
//do something
delete this;
}
}
注意:此答案适用于 C++03,并且似乎 C++11 及更高版本中的行为已更改,因此现在这是未定义的行为。
事实证明,在这种特殊情况下,代码是合法的,但是您远离未定义的行为。
C++03 标准将对象的“生命周期”定义为构造函数完成运行与析构函数开始运行之间的时间。它还明确指出(在 §3.8/5 中)
在对象的生命周期开始之前 [...] 如果对象将是或曾经是具有非平凡析构函数的类类型,并且指针用作删除表达式的操作数,则程序具有未定义的行为.
由于对象的生命周期直到构造函数完成才开始,因此在构造函数内部,this
您引用的指针还没有开始它的生命周期,delete
在这种情况下尝试它是完全安全的。但是,如果您为该类编写析构函数,那么您将立即在此处遇到未定义的行为。
此外,如果您更改构造函数以便在删除对象后尝试引用任何类的数据成员,您将获得未定义的行为。如果对象是在堆栈上分配的,您将获得未定义的行为。如果对象是静态的,您将获得未定义的行为。如果对象是使用 分配的new
,那么客户端将返回到它的指针将是无效的,并且使用它会导致未定义的行为。一般来说,不要尝试这样做!
我想在这里理解的第一件事是你为什么要做这样的事情?
构造函数是一个成员函数,你的对象实际上是在其中构造的,一旦它完全构造,你就可以删除一个对象,这就是为什么要做这样的事情 -
class A
{
public:
A()
{
delete this;
}
~A()
{
}
};
导致未定义的行为。
此外,补充一点,如果您delete this
在析构函数中执行,这也是不正确的,因为对象本身正在经历破坏并且delete this
在析构函数中执行将再次调用析构函数。
class A
{
public:
A()
{
}
~A()
{
delete this; // calls the destructor again.
}
};
假设您的对象永远不会被任何东西继承,这应该可以正常工作。您的构造函数运行,然后立即调用析构函数。如果有任何东西继承了这个对象,它将中断,因为这个构造函数将在继承构造函数之前被调用。