首先,我们来看一下下列代码

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属性去掉。

只是保险情况,干脆全设置成虚析构算啦,我想大家宁多打几个单词保险,也不想之后有错误又得一点点找然后改吧。毕竟也不差那一两个单词的空间。

虚析构函数的内存泄漏相关推荐

  1. Android Studio +MAT 分析内存泄漏实战

    点击打开链接 对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何查找内存泄露的. 首先什么是内存泄漏? 内存泄漏就是一些 ...

  2. 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?...

    五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...

  3. JVM学习笔记之-垃圾回收相关概念 System.gc()的理解 内存溢出与内存泄漏 STW 垃圾回收的并行与并发 安全点与安全区域 再谈引用:强引用 软引用 弱引用 虚引用 终结器引用

    System.gc()的理解 在默认情况下,通过System.gc()或者Runtime. getRuntime ( ).gc ()的调用,会显式触发Full GC,同时对老年代和新生代进行回收,尝试 ...

  4. 【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数

    我们都知道面向对象编程的三大特征是封装.继承.多态,今天我们就来说一下其中之一的多态. 概念: 多态: 多态字面意思就是多种形态,C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同 ...

  5. unique函数_C++智能指针2:(虚?)析构函数(标准与实现的差异)

    只要是有良心的 C++ 教材,总是会苦心孤诣地告诫初学者,在继承关系中,应该把父类的析构函数定义成虚函数.这已然成为一条铁律,如果违背,不仅有内存泄漏的风险,在多继承情况下甚至会出现未定义行为.因此, ...

  6. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  7. 多态基类与虚析构函数

    假设我们有一个基类A,很不幸的,A的析构函数是一个non-virtual.同时我们有一个派生类B,它派生自A. 我们定义了一个A类型指针,它指向的实际对象是B: A * ptr = new B; 然后 ...

  8. C++什么是内存泄漏

    内存泄漏 内存泄漏的分类 1. 堆内存泄漏 (Heap leak). 2. 系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 3. 没有将基类的析构函数定义为虚函数.当基类 ...

  9. 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数

    1.静态联编,是程序的匹配,连接在编译阶段实现,也称为早期匹配.重载函数使用静态联编. 2.动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编.switch语句和if语句是动态联编的例子. #i ...

最新文章

  1. list存储引用类型注意的问题
  2. java future设计模式
  3. Android 70道面试题汇总不再愁面试
  4. jupyter中python3如何导入文件_Python·Jupyter Notebook各种使用方法
  5. 《F4+2》—团队项目系统设计改进与详细设计
  6. 创建一个dynamics 365 CRM online plugin (一) - Hello World Plugin
  7. Word中标题、图表自动编号的方法
  8. Java 9,Jigsaw,JPMS和模块:个人探索
  9. ldconfig mysql_ldconfig命令介绍
  10. 日志处理(二) 日志组件logback的介绍及配置使用方法(转)
  11. 前端学习(786):数组创建的两种方式
  12. Rust 中的继承与代码复用
  13. [CodeForces332E]Binary Key
  14. 引commons-io工具类做文件的复制及导出
  15. 开启Hadoop/Yarn的日志监控功能,配置Spark历史服务,解决web端查看日志时的Java.lang.Exception:Unknown container问题
  16. @interface List
  17. 回撤率 python_最大回撤和最大回撤率的区别?
  18. 国学大师 master of Chinese culture
  19. 关于ttyS与ttySAC
  20. word或excel图片没有另存为怎么办

热门文章

  1. vscode边写代码边看变化
  2. SSM中使用redis做中间缓存,详细注释,代码可以运行
  3. 如何使用 chown 命令更改 Linux 中的所有权
  4. 计算机网络课题立项申请书,学校课题立项申请书
  5. toFixed()方法解读
  6. 摩托罗拉 moto X30 冠军版值得买吗 配置怎么样
  7. 想知道电脑c盘里文件各代表啥不?
  8. 开源轻量级 IM 框架 MobileIMSDK 的Uniapp客户端库已发布
  9. 华为通过ADB取消系统更新
  10. oppo手机隐藏的计算机冷知识,OPPO手机那些隐藏按键里的功能有什么用?