当前位置: 首页 > 图文教程 > 开发语言 > VC++ > C++中的废料收集

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 C++中的废料收集


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 59 ::
收藏到网摘: n/a

C++中的废料收集
作者:死猫

提交者:eastvc 发布日期:2003-9-20 10:01:25
原文出处:http://www.cpphelp.net/issue/gc.html


Java的爱好者们经常批评C++中没有提供与Java类似的废料收集(Gabage Collector)机制(这很正常,正如C++的爱好者有时也攻击Java没有这个没有那个,或者这个不行那个不够好),导致C++中对动态存储的官吏称为程序员的噩梦,不是吗?你经常听到的是内存遗失(memory leak)和非法指针存取,这一定令你很头疼,而且你又不能抛弃指针带来的灵活性。

在本文中,我并不想揭露Java提供的废料收集机制的天生缺陷,而是指出了C++中引入废料收集的可行性。请读者注意,这里介绍的方法更多的是基于当前标准和库设计的角度,而不是要求修改语言定义或者扩展编译器。

1 什么是废料收集?

作为支持指针的编程语言,C++将动态管理存储器资源的便利性交给了程序员。在使用指针形式的对象时(请注意,由于引用在初始化后不能更改引用目标的语言机制的限制,多态性应用大多数情况下依赖于指针进行),程序员必须自己完成存储器的分配、使用和释放,语言本身在此过程中不能提供任何帮助,也许除了按照你的要求正确的和操作系统亲密合作,完成实际的存储器管理。标准文本中,多次提到了“未定义(undefined)”,而这大多数情况下和指针相关。

某些语言提供了废料收集机制,也就是说程序员仅负责分配存储器和使用,而由语言本身负责释放不再使用的存储器,这样程序员就从讨厌的存储器管理的工作中脱身了。然而C++并没有提供类似的机制,C++的设计者Bjarne Stroustrup在我所知的唯一一本介绍语言设计的思想和哲学的著作《The Design and Evolution of C++》(中译本:C++语言的设计和演化)中花了一个小节讨论这个特性。简而言之,Bjarne本人认为,

“我有意这样设计C++,使它不依赖于自动废料收集(通常就直接说废料收集)。这是基于自己对废料收集系统的经验,我很害怕那种严重的空间和时间开销,也害怕由于实现和移植废料收集系统而带来的复杂性。还有,废料收集将使C++不适合做许多底层的工作,而这却正是它的一个设计目标。但我喜欢废料收集的思想,它是一种机制,能够简化设计、排除掉许多产生错误的根源。

需要废料收集的基本理由是很容易理解的:用户的使用方便以及比用户提供的存储管理模式更可靠。而反对废料收集的理由也有很多,但都不是最根本的,而是关于实现和效率方面的。

已经有充分多的论据可以反驳:每个应用在有了废料收集之后会做的更好些。类似的,也有充分的论据可以反对:没有应用可能因为有了废料收集而做得更好。

并不是每个程序都需要永远无休止的运行下去;并不是所有的代码都是基础性的库代码;对于许多应用而言,出现一点存储流失是可以接受的;许多应用可以管理自己的存储,而不需要废料收集或者其他与之相关的技术,如引用计数等。

我的结论是,从原则上和可行性上说,废料收集都是需要的。但是对今天的用户以及普遍的使用和硬件而言,我们还无法承受将C++的语义和它的基本库定义在废料收集系统之上的负担。”

以我之见,统一的自动废料收集系统无法适用于各种不同的应用环境,而又不至于导致实现上的负担。稍后我将设计一个针对特定类型的可选的废料收集器,可以很明显地看到,或多或少总是存在一些效率上的开销,如果强迫C++用户必须接受这一点,也许是不可取的。

关于为什么C++没有废料收集以及可能的在C++中为此做出的努力,上面提到的著作是我所看过的对这个问题叙述的最全面的,尽管只有短短的一个小节的内容,但是已经涵盖了很多内容,这正是Bjarne著作的一贯特点,言简意赅而内韵十足。

下面一步一步地向大家介绍我自己土制佳酿的废料收集系统,可以按照需要自由选用,而不影响其他代码。

2 构造函数和析构函数

C++中提供的构造函数和析构函数很好的解决了自动释放资源的需求。Bjarne有一句名言,“资源需求就是初始化(Resource Inquirment Is Initialization)”。

因此,我们可以将需要分配的资源在构造函数中申请完成,而在析构函数中释放已经分配的资源,只要对象的生存期结束,对象请求分配的资源即被自动释放。

那么就仅剩下一个问题了,如果对象本身是在自由存储区(Free Store,也就是所谓的“堆”)中动态创建的,并由指针管理(相信你已经知道为什么了),则还是必须通过编码显式的调用析构函数,当然是借助指针的delete表达式。

3 智能指针

幸运的是,出于某些原因,C++的标准库中至少引入了一种类型的智能指针,虽然在使用上有局限性,但是它刚好可以解决我们的这个难题,这就是标准库中唯一的一个智能指针::std::auto_ptr<>。

它将指针包装成了类,并且重载了反引用(dereference)运算符operator *和成员选择运算符operator ->,以模仿指针的行为。关于auto_ptr<>的具体细节,参阅《The C++ Standard Library》(中译本:C++标准库)。

例如以下