"稀奇古怪的"delete this
myClass::foo(){ delete this;}..void func(){ myClass *a = new myClass(); a->foo();}在类的成员函数中能不能调用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,形成无限递归,造成堆栈溢出,系统崩溃。
--------------------我是分界面--------------------
上面是某大牛的分析,而在实际的运行过程中使用delele this确实会直接出现错误。这是因为:在成员函数中调用delete this,首先会调用类的析构函数,this指针已删除,会出现指针错误。
下面是在XCode中使用delete this出现的错误:
malloc: *** error for object 0xbffffa18: pointer being freed was not allocated
//注意0xbffffa18即为this的地址
*** set a breakpoint in malloc_error_break to debug
而在VS2010中使用delete this是直接导致 Debug Assertion Failed!
具体的描述是:invalid null pointer
总结:在成员函数中调用delete this,会导致指针错误,而在析构函数中调用delete this,出导致死循环,造成堆栈溢出。
PS:this是类中成员函数具有的一个附加的隐含形参,即指向该类对象的一个指针,它与调用成员函数的对象绑定在一起。同时1.在普通的非const成员函数中:this的类型是一个指向类类型的const指针,可以改变this指向的值,但是不能改变this所保存的地址;2.在const成员函数中,this的类型是一个指向const类类型对象的const指针,既不能改变this所指向的对象,也不能改变this所保存的地址。
注意:
- 成员函数中不能定义this形参,而是由编译器隐含地定义,但是可以在成员函数中显示使用this形参,不过也不是必须这么做。如果对类成员的引用没有限定,编译器会将这种引用处理成通过this指针的引用。
- 有一种情况下必须显式使用this:当我们需要将一个对象作为整体引用而不是引用对象的一个成员时。
- 从const成员函数返回*this:不能从const成员函数返回指向类对象的普通引用。const成员函数只能返回*this作为一个const引用。
"稀奇古怪的"delete this的更多相关文章
- 如何区别数据库删除语句drop与delete与truncate?
1.delete:删除数据表中的行(可以删除某一行,也可以在不删除数据表的情况下删除所有行) 删除某一行:delete from 数据表名称 where 列名称=值: 删除所有行:delete*fro ...
- 数据库设计中的Soft Delete模式
最近几天有点忙,所以我们今天来一篇短的,简单地介绍一下数据库设计中的一种模式——Soft Delete. 可以说,该模式毁誉参半,甚至有非常多的人认为该模式是一个Anti-Pattern.因此在本篇文 ...
- 关于JavaScript中的delete操作
关于JavaScript中的delete操作 看到一道题,是这样的: (function(x){ delete x; return x; })(1); 1 null undefined Error 我 ...
- Git异常:Cannot delete the branch 'test1' which you are currently on
GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...
- HTTP Method详细解读(`GET` `HEAD` `POST` `OPTIONS` `PUT` `DELETE` `TRACE` `CONNECT`)
前言 HTTP Method的历史: HTTP 0.9 这个版本只有GET方法 HTTP 1.0 这个版本有GET HEAD POST这三个方法 HTTP 1.1 这个版本是当前版本,包含GET HE ...
- IIS7.5上的REST服务的Put,Delete操作发生HTTP Error 405.0 - Method Not Allowed 解决方法
WebDAV 是超文本传输协议 (HTTP) 的一组扩展,为 Internet 上计算机之间的编辑和文件管理提供了标准.利用这个协议用户可以通过Web进行远程的基本文件操作,如拷贝.移动.删除等.在I ...
- ASP.NET Core 中文文档 第二章 指南(4.10)检查自动生成的Detail方法和Delete方法
原文 Examining the Details and Delete methods 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).姚阿勇(Mr.Yao) 打 ...
- new/delete重载
在c++中,有时我们需要在运行阶段为一个变量分配未命名的内存,并使用指针来访问它,这里就可以用到new关键字.另外需要指出的是,new分配的内存块通常与常规变量分配的内存块不同,常规变量的值都储存在被 ...
- EC笔记:第三部分:16成对使用new和delete
我们都知道,申请的资源,使用完毕后要释放.但是这个释放动作,一定要注意. 举个例子,很多人动态分配的资源,在使用之后,往往直接调用了delete,而不管申请资源的时候用的是new还是new[]. 如下 ...
随机推荐
- Code First03---CodeFirst根据配置同步到数据库的三种方式
上一节我们说到使用Fluent API对实体的配置,但是有一个问题了,在业务中我们可以用到的实体很多,那是不是每个都需要这样去配置,这样就造成我们重写的OnModelCreating方法很庞大了.所以 ...
- PL/sql developer连接数据库的问题以及oracle数据库中文乱码的问题
今天第二次配置PL/sql developer,表示很蛋疼,昨天因为动了一个东西然后莫名其妙的就再也连接不了数据库,总是显示各种错误,我动的东西是因为中文会显示乱码,(因为我是用32位的PL/sql ...
- Codeforces 271 Div 2 B. Worms
题目链接:http://codeforces.com/contest/474/problem/B 解题报告:给你n个堆,第i个堆有ai个物品,物品的编号从1开始,第一堆的编号从1到a1,第二堆编号从a ...
- 简单易懂的crontab设置工具集
导读 在上一篇文章中,我介绍了crontab的配置文件以及如何设置定时任务,对于偶尔用一次crontab的同学而言,可能遗忘配置语法会很快,这里我向大家推荐几个在线设置crontab任务的网站. ge ...
- Android坐标系统
1 背景 去年有很多人私信告诉我让说说自定义控件,其实通观网络上的很多博客都在讲各种自定义控件,但是大多数都是授之以鱼,却很少有较为系统性授之于渔的文章,同时由于自己也迟迟没有时间规划这一系列文章, ...
- (转)listview中常见难题总结
原文地址:http://blog.csdn.net/cherry609195946/article/details/8844224 1. PopWindow中listview的item获取不到点击事件 ...
- BZOJ 1068: [SCOI2007]压缩
Sol 区间DP.这个区间DP需要三维, \(f[i][j][k]\) 表示\([i,j]\) 这个区间中是否存在 \(M\) . 转移有两种,一种是这个区间存在 \(M\) ,那么直接枚举 \(M\ ...
- python查找并删除相同文件-UNIQ File-script版本
今天用wxPython做了一个GUI程序,实现查找指定目录内的相同文件,主要原理是计算文件的md5值(计算前先找出文件大小相同的文件,然后计算这些文件的md5值,而不是所有文件都计算,大大减少了md5 ...
- Openstack Neutron 允许VM流量转发
neutron port-update <port-id> --port-security-enabled=False --no-security-groups
- jquery实现input输入框实时输入触发事件代码 ---jQuery 中bind(),live(),delegate(),on() 区别
复制代码 代码如下: <input id="productName" name="productName" value="" /> ...