虚析构函数的内存泄漏
首先,我们来看一下下列代码
class A
{
public :A():i(new int(1))
{cout<<"A"<<emsl;
}
~A()
{cout<<"A释放"<<endl;delete i;
}
virtual void show()
{cout<<"i="<<i<<endl;
}
private:int *i;
};class B : public A
{
public :B():j(new int(2))
{cout<<"B"<<emsl;
}
~B()
{cout<<"B释放"<<endl;delete j;
}
void show()
{cout<<"j="<<j<<endl;
}
private:int *j;
};
int main()
{
A *a=new B;
a->show();
delete a;
return 0;
}
这段代码编译虽然没有错误,但当我们运行的时候,我们会发现一个问题。
我们会得到一个这样的结果,我们构造了A,B,但我们最后释放却只释放了A,而B没有被释放,发生了内存泄漏。(在一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。)
怎么解决呢?
那就创建虚析构函数,在析构函数前加上virtual,将其变成虚函数。这样,我们的子类对象也可以正常的释放而不会造成内存泄漏了。
class A
{
public :A():i(new int(1))
{cout<<"A"<<emsl;
}
virtual ~A()//虚析构函数
{cout<<"A释放"<<endl;delete i;
}
virtual void show()
{cout<<"i="<<i<<endl;
}
private:int *i;
};class B : public A
{
public :B():j(new int(2))
{cout<<"B"<<emsl;
}
~B()
{cout<<"B释放"<<endl;delete j;
}
void show()
{cout<<"j="<<j<<endl;
}
private:int *j;
};
int main()
{
A *a=new B;
a->show();
delete a;
return 0;
}
造成这种现象的原因就在于当父类指针指向子类对象时,如果我们没有将析构函数设为虚函数,那他们之间就不会发生动态多态,而未发生动态多态那其就只会调用父类的析构函数,而子类未调用析构函数从而造成内存泄漏。
所以一般来说建议将父类析构设置为虚函数,避免在使用中造成内存泄漏。
当然这不是说所有的都得设置成这样。
例如有些类尽管可能会被继承,但不会被使用成多态的,即除了析构函数外,没有其他的的是virtual的,这时就可以把virtual属性去掉。
只是保险情况,干脆全设置成虚析构算啦,我想大家宁多打几个单词保险,也不想之后有错误又得一点点找然后改吧。毕竟也不差那一两个单词的空间。
虚析构函数的内存泄漏相关推荐
- Android Studio +MAT 分析内存泄漏实战
点击打开链接 对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何查找内存泄露的. 首先什么是内存泄漏? 内存泄漏就是一些 ...
- 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?...
五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...
- JVM学习笔记之-垃圾回收相关概念 System.gc()的理解 内存溢出与内存泄漏 STW 垃圾回收的并行与并发 安全点与安全区域 再谈引用:强引用 软引用 弱引用 虚引用 终结器引用
System.gc()的理解 在默认情况下,通过System.gc()或者Runtime. getRuntime ( ).gc ()的调用,会显式触发Full GC,同时对老年代和新生代进行回收,尝试 ...
- 【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数
我们都知道面向对象编程的三大特征是封装.继承.多态,今天我们就来说一下其中之一的多态. 概念: 多态: 多态字面意思就是多种形态,C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同 ...
- unique函数_C++智能指针2:(虚?)析构函数(标准与实现的差异)
只要是有良心的 C++ 教材,总是会苦心孤诣地告诫初学者,在继承关系中,应该把父类的析构函数定义成虚函数.这已然成为一条铁律,如果违背,不仅有内存泄漏的风险,在多继承情况下甚至会出现未定义行为.因此, ...
- C++中基类的析构函数为什么要用virtual虚析构函数
知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅: C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...
- 多态基类与虚析构函数
假设我们有一个基类A,很不幸的,A的析构函数是一个non-virtual.同时我们有一个派生类B,它派生自A. 我们定义了一个A类型指针,它指向的实际对象是B: A * ptr = new B; 然后 ...
- C++什么是内存泄漏
内存泄漏 内存泄漏的分类 1. 堆内存泄漏 (Heap leak). 2. 系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 3. 没有将基类的析构函数定义为虚函数.当基类 ...
- 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数
1.静态联编,是程序的匹配,连接在编译阶段实现,也称为早期匹配.重载函数使用静态联编. 2.动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编.switch语句和if语句是动态联编的例子. #i ...
最新文章
- list存储引用类型注意的问题
- java future设计模式
- Android 70道面试题汇总不再愁面试
- jupyter中python3如何导入文件_Python·Jupyter Notebook各种使用方法
- 《F4+2》—团队项目系统设计改进与详细设计
- 创建一个dynamics 365 CRM online plugin (一) - Hello World Plugin
- Word中标题、图表自动编号的方法
- Java 9,Jigsaw,JPMS和模块:个人探索
- ldconfig mysql_ldconfig命令介绍
- 日志处理(二) 日志组件logback的介绍及配置使用方法(转)
- 前端学习(786):数组创建的两种方式
- Rust 中的继承与代码复用
- [CodeForces332E]Binary Key
- 引commons-io工具类做文件的复制及导出
- 开启Hadoop/Yarn的日志监控功能,配置Spark历史服务,解决web端查看日志时的Java.lang.Exception:Unknown container问题
- @interface List
- 回撤率 python_最大回撤和最大回撤率的区别?
- 国学大师 master of Chinese culture
- 关于ttyS与ttySAC
- word或excel图片没有另存为怎么办