在类中调用delete this问题

转载: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,形成无限递归,造成

堆栈溢出,系统崩溃。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++中对多态的理解

1 多态&#xff1a;是指类中具有相似功能的不同函数&#xff0c;使用同一个名称来实现&#xff1b;是对类的行为再抽象&#xff1b;多态是通过重载函数和虚函数来实现的。 2 继承讨论的是类与类的层次关系&#xff0c;多态则是考虑在不同层次的类中&#xff0c;以及在同一个类…

C#.NET中的事件2

/** Created by SharpDevelop. * User: noo * Date: 2009-8-17 * Time: 15:34 * * 事件2 */usingSystem ;usingSystem .Windows .Forms ;classTest { staticvoidMain()//入口函数{ Form frmnewForm ();//新建一窗体frm.Text "我的窗体"; …

HTML学习之基础

HTML是网页的标记语言不是编程语言&#xff0c;有一些标记段组成。大小写不敏感&#xff0c;可以用常用的编辑器软件编写用浏览器打开即可 有不同的版本<!DOCTYPE html> <meta charset"utf-8">在<title>前为了能正常显示中文。 超链接&#xff1a;…

linux最基础的几个指令

cd 切换目录使用 pwd 显示当前目录路径 ls 列出目录内容 跟参数 -a 显示所有文件和目录 -A 显示所有文件包括隐藏-l 使用详细格式列出-d 显示目录名称而非内容-i 显示文件和目录的inode号-Z 显示文件和目录的上下文-R 子目录显示touch 创建文件或者改变文件时间 touch 2…

Advapi 登录类型8的错误

登录类型8&#xff1a;网络明文&#xff08;NetworkCleartext&#xff09; 这种登录表明这是一个像类型3一样的网络登录&#xff0c;但是这种登录的密码在网络上是通过明文传输的&#xff0c;WindowsServer服务是不允许通过明文验证连接到共享文件夹或打印机的&#xff0c;据我…

Varint

什么是Varint Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字&#xff0c;值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。 比如对于 int32 类型的数字&#xff0c;一般需要 4 个 byte 来表示。但是采用 Varint&#xff0c;对于很小的 …

Ubuntu 17.10安装Qt 5.10环境与Qt Creator 4.5开发工具(转自linux公社)

记录下在Ubuntu 17.10搭建Qt环境与安装Qt Creator开发工具的过程。机器装的Linux是Ubuntu 17.10&#xff0c;16.04与17.04的应该也相同。Qt 5.10和Qt 3D Studio发布 http://www.linuxidc.com/Linux/2017-12/149267.htm 1&#xff0c;Qt安装 1.1 下载Qt 这里提供Qt Creator的下…

服务器USB启动故障一例

前几日&#xff0c;本公司一台prop平台服务器&#xff08;hp 380G5服务器&#xff09;接上key&#xff08;usb口&#xff09;后&#xff0c;出现重启不能启动现象&#xff0c;进入服务器bios设置启动项为硬盘启动也不行&#xff0c;之后仔细查看服务器usb控制选项&#xff1a;可…

C#基础(201)--常量枚举

本文知识点&#xff1a; 1.掌握常量的定义和使用方法 2.理解枚举的作用和特点 3.掌握枚举的使用方法 1.1.常量的定义语法 const 数据类型 常量名称 值&#xff1b; 1.2.常见错误 1.3常量的使用时机 经常使用并且值不变的变量&#xff0c;可以定义为常量 2.1枚举的作用及其…

自定义EL函数解决JSTL标签不足之处——按字节长度截取字符串

题外话&#xff1a;做过大型网站前台的Web开发程序员最头疼的事情就是前台首页的布局&#xff0c;这其中最最头疼的就是标题字符的截取的问题&#xff0c;虽然有fn:substring&#xff0c;但表现率以及对中文的支持均不够完善&#xff0c;其实最终还是归结为客户要求太高了&…

进程之父子进程的关系

转载&#xff1a;https://blog.csdn.net/qq_28840229/article/details/79844763 fork之后&#xff1a; 父子相同处: 全局变量、.data、.text、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式... 父子不同处: 1.进程ID 2.fork返回值 3.父进程ID 4.进…

C语言快速排序算法

void sort(int *a, int left, int right) {if(left > right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/{return ;}int i left;int j right;int key a[left];while(i < j) /*控制在当组内寻找一遍*/{while(i &l…

unbuntu使用经典界面

为什么80%的码农都做不了架构师&#xff1f;>>> 昨天升级到UBUNTU 11.04, 发现新的Unity界面很不适应&#xff0c;于是将其恢复到旧式经典界面&#xff0c;具体操作模式方法如下&#xff1a; 在已经登录的状态下&#xff0c;选择 [注销]然后在重新登录的时候&#…

学习:深入浅出之正则表达式(转)

本文是Jan Goyvaerts为RegexBuddy写的教程的译文&#xff0c;版权归原作者所有&#xff0c;欢迎转载。但是为了尊重原作者和译者的劳动&#xff0c;请注明出处&#xff01;谢谢&#xff01; 1. 什么是正则表达式 基本说来&#xff0c;正则表达式是一种用来描述一定数量文本…

C语言判断计算机存储是大端还是小端

计算机的一个int型数据是用多个字节表示的&#xff0c;如果在内存中存放时标称该数据的地址中存放的是数据的最低字节&#xff0c;就叫小端机&#xff0c;反之把高字节存放在标称地址中的则称为大端机。所以可以定义一个int变量&#xff0c;将其地址强制为char *型地址&#xf…

服务器开发中网络数据分析与故障排查经验漫谈

转载大牛的文章&#xff1a; https://mp.weixin.qq.com/s/6ZmiKUz4ZQvwLXkzzBrFcg

每天干的啥?(2019.3)

【本年目标】 【本月目标】【本月总结】 【3月每日记录】 去洗照片24张9寸&#xff0c;研究手机root&#xff08;y66不支持啊&#xff09;&#xff0c;下午党学习照相、看完第4课blake《用户数据ugame》、研究轮滑gif、晚上钢琴首次调律。 去妈妈那吃饭&#xff0c;学钢琴、佰洲…

【Andorid X 项目笔记】禁用ListView的Fling功能(1)

前言新的项目正在紧张开发中&#xff0c;初步估计2个月时间开发完成第一版&#xff0c;我负责Android端开发&#xff0c;由于不便过早公布&#xff0c;本系列将命名为“X项目笔记”&#xff0c;并于项目结束后最终公布名称。本系列主要记录与分享"X项目"中遇到的问题…

C语言题目地图上有m个城市,序号依次为1,2,3....m,刚开始你在1,若每次只能从当前城市去往当前序号加1或者加3的城市,要到达m城市(m3),有多少种走法

地图上有m个城市&#xff0c;序号依次为1,2,3....m&#xff0c;刚开始你在1&#xff0c;若每次只能从当前城市去往当前序号加1或者加3的城市&#xff0c;要到达m城市&#xff08;m>3&#xff09;,有多少种走法 要想到达m&#xff0c;则前一个应该是m - 1或者m -3&#xff1b…

Java IO/NIO教程

Java IO教程 http://tutorials.jenkov.com/java-io/index.html Java NIO教程 英文版&#xff1a; http://tutorials.jenkov.com/java-nio/index.html 中文版: Java NIO概述Java NIO ChannelJava NIO BufferJava NIO Scatter / GatherJava NIO 通道之间的数据传输Java NIO Selec…