首先您必须定义什么是C++程序中的“垃圾”,以及什么仅仅是对象生命周期。问题就在于这样的想法:即应该销毁废弃的对象,并回收它们占用的内存块以供系统使用,以在适当的时候不中断系统或使正在运行的程序缺少内存资源。那么问题是如何在C ++中放弃对象?应该这样做吗?
C ++在三种不同的内存区域中以三种不同的方式创建对象:
首先是静态内存区域,其中放置了静态(全局)变量和名称空间变量,类变量,静态函数变量。这些静态变量在程序启动时分配,并持续到程序终止。除非结束程序,否则无法恢复该内存。
文字是诸如字符串和常量之类的东西,以及诸如系统变量和其他值之类的常数表达式,它们在程序的生命周期中从未改变。C ++将它们放在只读存储器中以便快速访问。
其次是堆栈; 堆栈是一个内存段,由编译器完全管理,并且在程序运行时大小保持固定。不需要或没有能力手动分配,更或者删除堆栈存储器或堆栈对象。即使发生异常,堆栈及其内容也永远不会“泄漏”。
在堆栈上创建的对象超出范围时会自动释放其资源。
最后,还有动态内存堆,在这里发生泄漏以及大量分配和删除。堆上的对象使用new 运算符创建并保留,直到使用delete 运算符将其显示删除为止,否则程序将终止。
然而危险就在这里。编译器无法告知何时将删除堆分配的对象,或者在调用删除对象后是否尝试访问该对象。这不是泄漏,但它是内存冲突并导致程序崩溃的原因。
如果C ++中的指针指向有效对象,某个随机内存位置或NULL或指向中间的某处,则可以在任何给定时间更改C ++指向的指针,并且不向编译器提供任何信息。分配给其他对象或数据的堆。一个对象也可以有多个指向它的指针。因此,处理此问题的方法是不处理它。C ++让编码器为王,并按自己的意愿去做,假设他们使用的是new和Delete,他们就知道自己在做什么。只要语法正确,您就可以自由地到那里在内存中生成活动对象,然后随意删除它们。
“丢弃指针”是C ++中需要垃圾收集器的原因。您有一个指向对象的指针,并将其分配为指向相同类型的新对象。那老对象呢?它会一直保留在内存中,直到被删除为止,但是现在您没有“句柄”可以用它来调用delete了因为您已经忘了它。因此,它坐在那里徘徊其内存块,等待引起麻烦。因为当您尝试创建另一个新对象时,操作系统会将内存标记为已分配,并且确实会导致安装失败,并且拒绝为您分配新对象,并且可能会使您的程序在没有保存的情况下立即崩溃。因此,您的程序在没有明显原因的情况下会突然跳动,突然出现故障,并且在这种情况下很难发现问题,并且需要复杂的工具和许多深夜伤害您的眼睛。
但是C ++可以避免这种情况。C ++具有编程方法和称为引用的特殊类型,它们类似于指针,但会对自身进行一些检查以验证它们是否实际指向有效对象,并且对如何使用指针所没有的限制。类对象默认带有自己的析构函数,并且对象继承模型鼓励良好的内存习惯。
标准模板库(STL)是C ++的官方默认库,并且随编译器套件的每个实现一起提供。它具有动态容器,例如矢量和数组以及列表和地图,这些容器虽然可以增长和收缩,但仍是静态分配的。它们会照顾它们所包含的对象,并且在容器被破坏或超出范围时会自动调用其析构函数。
STL还具有智能指针。现在,智能指针不再是指针。它们是静态分配的类,但包含指向对象指针或对象指针组的指针。通过将对它的任何调用直接传递到内部对象,智能指针对象的行为类似于实际的对象指针。就像它是内部动态分配对象周围的不可见包装器一样。
当智能指针被明确销毁或自然超出范围时,智能指针中所有对象的析构函数也将被正确销毁。
智能指针的销毁保证了它指向的对象也将被销毁。
在这样的系统中,垃圾收集器要么要么非常复杂,并且要花费大量时间与主程序任务时间间隔,要么必须完全处于休眠状态,直到显示调用它为止,然后在分配给它的时间段内执行可能的操作。确实存在此类临时解决方案,但它们仅适用于独特的用例,不适合可靠的生产代码。
因此,为了维护速度,效率和功率的C ++模型,同时损害某些安全功能,C ++委员会尚未决定将垃圾收集器作为C ++标准编译器套件或STL的一部分。
热门跟贴