0

我正在阅读安全的 C++,作者提到了如下循环引用。

考虑两个包含彼此指针的对象

class A;

class B { public: A* a; };

class A { public: B* b; };

这种情况被称为“循环引用”。指向 A 和 B 的指针存在,但如果没有其他指针指向来自其他地方的这些对象中的至少一个,则无法为任一变量回收内存,因此会造成内存泄漏。这两个对象将永远幸福地生活,永远不会被摧毁。

我的问题

  1. 为什么会出现内存泄漏?为什么在相应类的析构函数中删除内存是个坏主意?
  2. 作者在什么基础上提到两个物体从此存在?

感谢您的时间和帮助

4

2 回答 2

4

有一些垃圾收集算法非常简单,以至于它们无法收集两个相互引用的无法访问的对象(基本上,如果 gc 仅使用引用计数)。

但是,C++ 根本不保证提供任何垃圾收集。而且您显示的代码甚至不使用引用计数。因此,就您所展示的内容而言,泄漏对象(如果泄漏任何对象)的原因与循环引用无关,这是因为您没有释放它们。

您引用的书似乎是在您选择不在此问题中显示的一些附加信息的背景下说的——可能书中有一些参考计数。

于 2013-03-14T08:56:21.013 回答
0

有问题的概念是可达性。基本上,从一组基本指针(活动变量等)开始,您可以直接或间接访问相关对象。如果不是,则该对象不可访问。

一个不可达对象的简单例子是没有指针的对象。循环引用示例是另一个示例:存在指向两个对象的指针,但对象仍然不可访问。

在大多数语言中,如果一个对象是不可访问的,它迟早会被垃圾回收。在 C++ 中,您需要在任何动态分配的对象变得无法访问之前显式删除它;否则,您永远无法删除它(并且内存已泄漏)。一种常用的 C++ 模拟垃圾收集技术是引用计数指针。这种技术(与其他垃圾收集技术不同)不能正确处理循环引用,因此会泄漏内存。

虽然 C++ 会从垃圾收集中受益,但重要的是要意识到这在 C++ 中不像在大多数其他语言中那样严重。在 C++ 中,动态分配的对象通常只对应于具有定义生命周期的对象,并且会在响应某些外部事件时显式销毁(或者永远不会被销毁,因为一旦程序完成了它们,程序就完成了,时期——想想编译器中的解析树)。因为 C++ 支持值语义,所以大多数其他对象不支持 动态分配,而是局部变量,或更大对象的数据成员,并自动管理其生命周期。尽管 C++ 有许多“智能”指针来自动管理删除内存,但如果您发现自己被广泛使用它们所吸引,那么您可能正在滥用动态分配。

于 2013-03-14T09:08:34.867 回答