首页 > 试题广场 >

关于以下代码,哪个说法是正确的?

[单选题]
关于以下代码,哪个说法是正确的?
myClass::foo(){
    delete this;
}
..
void func(){
    myClass *a = new myClass();
    a->foo();
}
  • 它会引起栈溢出
  • 都不正确
  • 它不能编译
  • 它会引起段错误
出处:http://blog.sina.com.cn/s/blog_4b4cf2af0100ywgv.html
在类的成员函数中能不能调用delete this?答案是肯定的,能调用,而且很多老一点的库都有这种代码。假设这个成员函数名字叫release,而delete this就在这个release方法中被调用,那么这个对象在调用release方法后,还能进行其他操作,如调用该对象的其他方法么?答案仍然是肯定 的,调用release之后还能调用其他的方法,但是有个前提:被调用的方法不涉及这个对象的数据成员和虚函数。说到这里,相信大家都能明白为什么会这样 了。

根本原因在于delete操作符的功能和类对象的内存模型。当一个类对象声明时,系统会为其分配内存空间。在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内容,类的成员函数单独放在代码段中。在调用成员函数时,隐含传递一个this指针,让成员函数知道当前是哪个对象在调用它。当 调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要不涉及到this指针的内容,都能够正常运行。一旦涉及到this指针,如操作数据成员,调用虚函数等,就会出现不可预期的问题。

为什么是不可预期的问题?delete this之后不是释放了类对象的内存空间了么,那么这段内存应该已经还给系统,不再属于这个进程。照这个逻辑来看,应该发生指针错误无访问权限之类的令系统崩溃的问题才对啊?这个问题牵涉到操作系统的内存管理策略。delete this释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,可能是缓冲或者其他什么原因,导致这段内存空间暂时并没有被系统收回。此时这段内存是可以访问的,你可以加上100,加上200,但是其中的值却是不确定的。当你获取数据成员,可能得到的是一串很长的未初始化的随机数;访问虚函数表,指针无效的可能性非常高,造成系统崩溃。


大致明白在成员函数中调用delete this会发生什么之后,再来看看另一个问题,如果在类的析构函数中调用delete this,会发生什么?实验告诉我们,会导致堆栈溢出。原因很简单,delete的本质是“为将被释放的内存调用一个或多个析构函数,然后,释放内存” (来自effective c++)。显然,delete this会去调用本对象的析构函数,而析构函数中又调用delete this,形成无限递归,造成堆栈溢出,系统崩溃

发表于 2015-09-11 11:20:25 回复(18)
总结一下 一,在foo()中调用delete this;没有问题,但是在析构函数中调用则会由于delete this会自动调用析构函数的原因造成无限递归,导致栈溢出。二,调用完delete this 之后,对象的内存空间被释放了,导致不能再访问数据成员和虚函数
发表于 2016-11-16 14:04:04 回复(4)
这段代码应该没有问题:
a 是一个类指针,指向一个动态分配的类;
foo是该类的成员函数,而成员函数具有一个隐含形参:一个指向调用该函数的类对象的指针,即this指针;
当通过指针a 调用函数foo 时,this 指针就是 a指针了,所以delete this 就等于 delete a,也就是释放掉动态分配的内存。

发表于 2015-09-05 19:26:46 回复(0)
前面各位都从理论上分析的很清楚,我实际测试了一下,结果如下:
可以看到,foo中delete的作用就是析构的作用。类似于手动的析构,所以在程序结束后就不会在调用类默认的析构函数,故不会发生错误。

发表于 2017-07-03 09:55:02 回复(1)
调用foo函数释放了动态分配的内存之后,垃圾回收站会检查是否有应用程序不再使用的对象,若有,则接着调用析构函数回收,否则不调用
发表于 2015-09-07 23:21:03 回复(0)

foo中
delete this 后会导致析构函数被调用。

若放析构函数中会导致无限循环。

因此是B
发表于 2015-09-05 20:03:35 回复(0)
清晰!
在类的成员函数中能不能调用delete this?答案是肯定的,能调用,而且很多老一点的库都有这种代码。假设这个成员函数名字叫release,而delete this就在这个release方法中被调用,那么这个对象在调用release方法后,还能进行其他操作,如调用该对象的其他方法么?答案仍然是肯定 的,调用release之后还能调用其他的方法,但是有个前提:被调用的方法不涉及这个对象的数据成员和虚函数。说到这里,相信大家都能明白为什么会这样 了。

根本原因在于delete操作符的功能和类对象的内存模型。当一个类对象声明时,系统会为其分配内存空间。在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内容,类的成员函数单独放在代码段中。在调用成员函数时,隐含传递一个this指针,让成员函数知道当前是哪个对象在调用它。当 调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要不涉及到this指针的内容,都能够正常运行。一旦涉及到this指针,如操作数据成员,调用虚函数等,就会出现不可预期的问题。

为什么是不可预期的问题?delete this之后不是释放了类对象的内存空间了么,那么这段内存应该已经还给系统,不再属于这个进程。照这个逻辑来看,应该发生指针错误无访问权限之类的令系统崩溃的问题才对啊?这个问题牵涉到操作系统的内存管理策略。delete this释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,可能是缓冲或者其他什么原因,导致这段内存空间暂时并没有被系统收回。此时这段内存是可以访问的,你可以加上100,加上200,但是其中的值却是不确定的。当你获取数据成员,可能得到的是一串很长的未初始化的随机数;访问虚函数表,指针无效的可能性非常高,造成系统崩溃。


大致明白在成员函数中调用delete this会发生什么之后,再来看看另一个问题,如果在类的析构函数中调用delete this,会发生什么?实验告诉我们,会导致堆栈溢出。原因很简单,delete的本质是“为将被释放的内存调用一个或多个析构函数,然后,释放内存” (来自effective c++)。显然,delete this会去调用本对象的析构函数,而析构函数中又调用delete this,形成无限递归,造成堆栈溢出,系统崩溃


发表于 2022-03-16 10:18:10 回复(0)
一、该函数没有返回值。
二、无法确定声明的时候是否是static成员函数。
发表于 2020-03-30 12:09:59 回复(0)
类对象的清除工作
发表于 2025-06-13 08:20:23 回复(0)
成员函数有返回值?
发表于 2024-05-29 22:41:42 回复(0)
为啥不会引起段错误,在foo种a对象被delete了,又因为a是func里面的局部变量,退出时又被delete一遍。
发表于 2020-06-23 17:30:27 回复(0)
emmmmm,foo()方法没有设定void,肯定会报错,不能编译啊
发表于 2018-09-22 14:12:26 回复(0)
vs2013编译报错啊
发表于 2017-07-06 21:26:05 回复(0)
纠错
发表于 2016-10-06 12:25:38 回复(0)
没有语法错误,只是不再调用了
发表于 2015-09-12 17:27:03 回复(1)