- OSG 提供了一种自动的“废弃物”收集系统,它使用一种名为内存引用计数器(referencecounted memory)的方式工作。所有的 OSG 场景图形节点均采用引用计数(reference count)的方式,当引用计数值减为 0 时,此对象将被自动释放。
- OSG 的“废弃物”收集系统有以下两个组件:
- 通用的基类
osg::Referenced
, 所有的 OSG 节点和场景图形均继承自这一基类,它包含了一个整型的引用计数器。 - OSG 定义的智能指针模板类
ref_ptr<>
。当代码中一个Referenced
对象指针赋予类型变量ref_ptr<>
时,Referenced
类的引用计数器会自动加 1。
- 通用的基类
- 如果程序要保存一个继承自
Referenced
的对象的指针,那么将指针保存在ref_ptr< >
中要好过使用标准 C++指针变量。如果代码中可以始终遵循这一原则,那么当最后一个引用对象的ref_ptr< >
被弃用时,对象所占用的内存将自动释放。当你创建任何继承自Referenced
的场景图形节点或数据时, 你的应用程序不可以直接释放其内存空间。除了极少数例外,几乎所有的Referenced
派生类都声明了保护析构函数。这样可以保证,继承自Referenced
的对象只能够通过减少引用计数器到 0 的方式来释放其内存。
Referenced
类Referenced
类(命名空间:osg
)实现了对内存区段的引用计数器功能。所有的 OSG 节点和场景图形数据,包括状态信息,顶点数组,法线,以及纹理坐标,均派生自Referenced
类。因此,所有的 OSG 场景图形均可以进行内存引用计数。Referenced
类包括了三个主要组成部分:- 保护成员整型变量
_refCount
,用作引用计数,在构造时被初始化为 0。 - 公有函数
ref()
和unref(
),用于实现_refCount
值的增加和减少。当_refCount
为 0 时,unref()
将自动释放该对象所占用的内存。 - 作为保护成员存在的虚析构函数。堆栈的创建和显示的析构均会因为析构函数受保护而被禁止,而虚函数的特性将允许用户执行子类的析构函数。
- 保护成员整型变量
- 总体上来说,用户的代码基本上不需要直接调用
ref()
和unref()
函数,只要使用ref_ptr<>
进行处理即可。
ret_ptr< >
模板类ref_ptr<>
(命名空间:osg
)用于实现一个指向Referenced
对象的智能指针,并对其引用计数器进行管理。当最后一个引用Referenced
对象的ref_ptr<>
失去作用时,对象将确保被释放。ref_ptr<>
简化了场景图形内存释放的工作,并保证当错误的调用堆栈展开时,对象也可以被正确释放。ref_ptr<>
模板类包括以下三个主要的组成部分:- 一个私有指针
_ptr
,用于保存管理内存区域的地址。可以用get()
方法返回_ptr
的值。 - 为了使
ref_ptr< >
可以像正常的 C++指针一样工作, 重载或定义了一些方法,如operator->()
和operator=()
。 valid()
方法用于判断ref_ptr<>
是否为空,不为NULL
时返回TRUE
。当程序将一个地址指定给ref_ptr<>
变量时,ref_ptr<>
的重载函数operator=()
将会假定此地址指向一个Referenced
派生对象,并自动调用Referenced::ref()
,将引用计数值自动加一。
- 一个私有指针
ref_ptr< >
变量的引用计数值减少的情形有这样两种:ref_ptr< >
被释放(在类的析构函数里执行减一),或者重新进行了赋值(在operator=()
里执行减一)。在以上两种情况中,ref_ptr< >
都会通过调用Referenced::unref()
来执行减少引用计数值的操作。
- 将派生自
Referenced
的对象赋予ref_ptr< >
变量,这一动作将自动调用Referenced::ref()
并使引用计数加一。- 如果将
ref_ptr< >
变量指向其它的对象,或者将其释放,那么将调用Referenced::unref()
方法,使引用计数减一。当计数器的值为0时,unref()
自动释放对象所占用的内存空间。 - 为新的
Referenced
对象开辟内存空间时,要尽量将其赋予ref_ptr< >
,以保证 OSG 的内存管理工作正确。
- 如果将