转载:https://blog.csdn.net/kuimzzs/article/details/81517451
很多时候,一些定义在类内的变量的生命周期在类外并不是很好的掌控,这样就很容易造成内存泄漏得到问题
比如以下代码:
class Test
{
public:
void foo();
private:
char *p;
};
void Test::foo()
{
p = new char[50];
}
int main()
{
Test t1;
t1.foo();
return 0;
}
这是一个很典型的例子,new到的堆上空间并没有主动释放,即使程序结束也不会自动清除(不过现在操作系统比较高级,会强制返还程序运行前的内存....但这并不是我们不养成良好习惯的理由)。
那么这时候,在析构函数中加入delete[] p就是个很好的习惯。
那么,正题来了,如果我们在成员函数中delete自己会怎么样?
delete this
下面通过代码来看:
class Test
{
public:
Test(int _x);
void foo();
void show();
void show(int);
private:
int x;
};
Test::Test(int _x) :x(_x)
{
}
void Test::show()
{
cout << “x =” << x << endl;
}
void Test::show(int)
{
cout << "this is show int"<< endl;
}
void Test::foo()
{
delete this;
}
int main()
{
Test *t1 = new Test(5);
cout << "before" << endl;
t1->show();
t1->foo();
cout << "after" << endl;
//t1->show();
t1->show(1);
system("pause");
return 0;
}
首先编译。结果是通过!证明在成员函数中调用delete this 并没有语法错误。
接下来运行:现在after后调用show(int)看delete this之后还能否调用成员函数。
结果如下图:
可以看到,delete this之后,该对象的成员函数还能调用。
那么,我们接下来就再次调用show()函数来看delete this 之后该对象中值释放还在。
结果如下图:
从结果来看,x已经变成随机值,看来对象内存空间的确是被释放了。
总结:
在类的成员函数可以调用delete this,并且delete this之后还可以调用该对象的其他成员,但是有个前提:被调用的方法不涉及
这个对象的数据成员和虚函数。
当一个类对象声明时,系统会为其分配内存空间。在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内
容,类的成员函数单独放在代码段中。在调用成员函数时,隐含传递一个this指针,让成员函数知道当前是哪个对象在调用它。
当 调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要不涉及到this指针的内容,都
能够正常运行。一旦涉及到this指针,如操作数据成员,调用虚函数等,就会出现不可预期的问题,即上面出现的随机值。
为什么会出现这种情况?delete this之后不是释放了类对象的内存空间了么,那么这段内存应该已经还给系统,不再属于这个
进程。照这个逻辑来看,应该发生指针错误,无访问权限之类的令系统崩溃的问题才对啊?这个问题牵涉到操作系统的内存管理
策略。delete this释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,可能是缓冲或者其他什么原因,导致
这段内存空间暂时并没有被系统收回。此时这段内存是可以访问的,你可以加上100,加上200,但是其中的值却是不确定的。当
你获取数据成员,可能得到的是一串很长的未初始化的随机数;访问虚函数表,指针无效的可能性非常高,造成系统崩溃。
而若是在析构函数中呢?delete this会去调用本对象的析构函数,而析构函数中又调用delete this,形成无限递归,造成
堆栈溢出,系统崩溃。