转载于:http://hi.baidu.com/chenfalei/blog/item/f39b0ae99fea763bb90e2d1f.html
深析C++析构函数
[ 作者: 袁凯 添加时间: 2001-9-27 9:28:23 ]
华南理工大学计算机研究所北区研发二部 袁凯
所有C++程序员对析构函数都不陌生,由于其简单且易理解,所以都能很快应用。这里我不说这些常用方法,若不知可参考C++书籍。而我这次所想说的是较微妙的技巧,常不被人注意,但却非常非常的重要。看以下代码:
//////////////////////////////////////////////////////
//Example 1
//author:
//date: 2001-09-24
//////////////////////////////////////////////////////
#include <iostream.h>
class CFunction
{
public:
CFunction()
{
data = new char[64];
};
~CFunction()
{
delete [] data;
};
char *data;
};
class CFunctionEx : public CFunction
{
public:
CFunctionEx()
{
m_data = new char[64];
};
~CFunctionEx()
{
delete [] m_data;
};
private:
char *m_data;
};
void main()
{
CFunction *pCFun = new CFunctionEx;
delete pCFun;
}
你能看出什么问题吗?很显然,有内存泄漏。这是因为当删除pCFun时,它只调用了Cfunction的析构函数而没调用CfunctionEx的析构函数,所以导致内存泄漏。再看下例:
//\\////\\////\\////\\////\\////\\//\\////\\////\\//
//Example 2
//author:
//date: 2001-09-24
//\\////\\////\\////\\////\\////\\//\\////\\////\\//
#include <iostream.h>
class CBase
{
public:
CBase()
{
data = new char[64];
};
~CBase()
{
delete [] data;
};
char *data;
};
class CFunction
{
public:
CFunction(){};
~CFunction(){};
};
class CFunctionEx : public CFunction
{
public:
CFunctionEx(){};
~CFunctionEx(){};
private:
CBase m_cbase;
};
void main()
{
CFunction *pCFun = new CFunctionEx;
delete pCFun;
}
你能看出什么问题吗?这里CfunctionEx和Cfunction中本身并没有分配内存,应该不会有内存泄漏。和上例一样当删除pCFun时,它只调用了Cfunction的析构函数而没调用CfunctionEx的析构函数,但CfunctionEx本身并没分配内存,是什么地方有内存泄漏我不说大家也应该知道了吧。不错是m_cbase,因为它是Cbase的实例且是CfunctionEx成员变量,当CfunctionEx的的析构函数没有被调用时,当然m_cbase的析构函数也没有被调用,所以Cbase中分配的内存被泄漏。
解决以上问题的方法很简单,就是使基类Cfunction的析构函数为虚函数就可以了。很简单,是吗?哈哈……
这样就得出一个结论,当你的基类的析构函数不为虚的话,
1.1
2.2 其子类中所有的成员变量的类中分配的内存也将可能泄漏。
第二点非常重要,因为很容易被遗漏。我就是为此这才写此文。
这里说的可能是因为,如果程序中没有以上示例类似写法(指用基类指针指向子类实例裕,虚函数是C++的精华,很少有人不用的,由其是在大中型软件项目中),就不会出现本文所说的内存泄漏。看来在基类中使析构函数为虚函数是如此的重要。所以强烈建议在基类中把析构函数声明为虚函数,但是只有你写的类并不做为基类时例外。
以上我在工作中碰到的问题,程序在VC++6中测试,内存泄漏对于一个高效的服务程序来说十分重要。我想可能大家也可能出现过这种问题,所以写出这篇文章,希望能给大家带来帮助。文章写的仓促,有错别字或错误请大家多包涵。欢迎和大家交流。其子类中所分配的内存将可能泄漏。袁凯袁凯
分享到:
相关推荐
8.4.4 基类和派生类的析构函数 8.4.5 医生也是人 8.4.6 关于派生类和基类构造函数的规则 8.5 多态和虚函数 8.5.1 多态——同一个接口,不同的行为 8.5.2 什么是虚函数 8.5.3 虚函数的作用 8.6 总结 8.7 练习 复习题...
main() //C++中main()函数默认为int型,而C语言中默认为void型。 { int a; cout; cin>>a; /*输入一个数值*/ cout; //输出并回车换行 return 0; } cin,cout,endl对象,他们本身并不是C++语言的组成部分。...
Effective C++(编程的50个细节)着重讲解了编写C++程序应该注意的50个细节问题,书中的每一条准则描述了一个编写出更好的C++的方式,每一个条款的背后都有具体范例支持,书中讲的都是C++的编程技巧和注意事项,很多都...
1.2为什么C++会成功 1.2.1较好的C 1.2.2采用渐进的学习方式 1.2.3运行效率 1.2.4系统更容易表达和理解 1.2.5“库”使你事半功倍 1.2.6错误处理 1.2.7大程序设计 1.3方法学介绍 1.3.1复杂性 1.3.2内部原则 1.3.3...
c++入门,简单快捷,很适合c++初学者 ...多态性……231 17.7多态与虚函数……231 17.8虚函数与虚析构函数……236 17.9抽象类与纯虚函数……238 17.10 多重继承……241 习题……242 第十八章再谈输入与输出……261
子类继承父类大部分的资源,不能继承的有构造函数,析构函数,拷贝构造函数,operator=函数,友元函数等等 15.为什么要引入抽象基类和纯虚函数? 主要目的是为了实现一种接口的效果。 16.介绍一下模板和容器。如何...
8.4.4 基类和派生类的析构函数 8.4.5 医生也是人 8.4.6 关于派生类和基类构造函数的规则 8.5 多态和虚函数 8.5.1 多态——同一个接口,不同的行为 8.5.2 什么是虚函数 8.5.3 虚函数的作用 8.6 总结 8.7 练习 复习题 ...
条款07:为多态基类声明Virtual析构函数 条款08:别让异常逃离析构函数 条款09:绝不在构造和析构过程中调用Virtual函数 条款10:令Operator=返回一个referenceto this 条款11:在Operator=中处理“自我赋值” ...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 ...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 ...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 ...
9.9.7 引用类的析构函数和结束函数 514 9.9.8 通用类 516 9.10 小结 527 9.11 练习 528 第10章 调试技术 531 10.1 理解调试 531 10.1.1 程序故障 532 10.1.2 常见故障 533 10.2 基本的调试操作 534...
51 3.6.1 可见的实现部分 51 3.6.2 减少重复编译 52 3.7 小结 54 3.8 练习 54 第4章 初始化与清除 55 4.1 用构造函数确保初始化 55 4.2 用析构函数确保清除 56 4.3 清除定义块 58...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 ...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 ...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 ...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省...
4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 ...
析构函数内联的主要原因是其定义在类的定义中,为了方便抑或是对其行为给出文档。 4. 函数参数顺序(Function Parameter Ordering) 定义函数时,参数顺序为:输入参数在前,输出参数在后。 C/C++ 函数参数分为...