OSG开发笔记(六):OSG内存管理

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/95042433

目录

前言

建立场景前需知道的内存管理

连锁释放

连锁释放依赖的组件

相关类

Referenced类

ret_ptr< >模板类

内存管理示例

示例1

示例2

示例3

示例4

总结

参考资料


 

OSG三维开发专栏

OSG开发笔记(一):OSG介绍、编译

OSG开发笔记(二):OSG帮助文档编译

OSG开发笔记(三):OSG使用osgQt嵌入Qt应用程序

OSG开发笔记(四):OSG不使用osgQt重写类嵌入Qt应用程序》:

OSG开发笔记(五):OSG场景理解与基础类概述

OSG开发笔记(六):OSG内存管理

OSG开发笔记(七):OSG复现OpenGL入门示例和OSG坐标系

OSG开发笔记(八):OSG模型文件存储与读取

OSG开发笔记(九):OSG模型的基本操作之添加/删除、显示/隐藏、开关节点开/》:

OSG开发笔记(十):OSG模型的变换之平移、旋转和缩放

OSG开发笔记(十一):OSG渲染状态与2D纹理映射

OSG开发笔记(十二):OSG基本几何图形、内置几何类型

OSG开发笔记(十三):OSG三维纹理映射(体渲染)

OSG开发笔记(十四):OSG交互

OSG开发笔记(十五):OSG光照

OSG开发笔记(十六):OSG视口、相机和视点

OSG开发笔记(十七):OSG中的相机移动

OSG开发笔记(十八):OSG鼠标拾取pick、拽托球体以及多光源

OSG开发笔记(十九):OSG文字显示

OSG开发笔记(二十):OSG使用HUD显示文字

OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

OSG开发笔记(二十二):OSG场景背景

OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG地球仪

OSG开发笔记(二十四):OSG漫游之平移、转向和低抬头

OSG开发笔记(二十五):OSG漫游之CS移动、碰撞检测与跳跃

OSG开发笔记(二十六):OSG漫游之上下楼梯

《OSG开发笔记(二十七):OSG路径漫游之录制播放固定路径动画

《OSG开发笔记(二十八):OSG模型固定路径动画

  持续补充中…

 

            OSG开发笔记(六):OSG内存管理

 

前言

        前篇介绍了类,在开发前还需要知道osg强大的内存管理功能。

 

建立场景前需知道的内存管理

        在开始建立场景图形之前,你需要对 OSG 场景图形节点和数据所使用的内存管理机制有所了解。对这一概念的掌握将有助于编写清洁的代码,并避免出现悬挂指针和内存泄露。

        当应用程序不再使用场景图形时,每个节点所使用的内存需要释放以避免内存泄露。如果要编写代码遍历整个场景图形,并依次删除所有的节点及其数据,那么这项工作将是巨大且容易出错的。

连锁释放

        OSG 提供了一种自动的“废弃物”收集系统,它使用一种名为内存引用计数器(referencecounted memory)的方式工作。所有的 OSG 场景图形节点均采用引用计数(reference count)的方式,当引用计数值减为 0 时,此对象将被自动释放。其结果是,删除如图 2-1 所示的场景图形时,程序只需要简单地释放指向根节点的指针。这一动作将引发连锁的效果,将场景图形中的所有节点和数据逐一释放。

        OSG开发笔记(六):OSG内存管理_第1张图片

        OSG开发笔记(六):OSG内存管理_第2张图片

        OSG开发笔记(六):OSG内存管理_第3张图片

        

 

连锁释放依赖的组件

        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()来执行减少引用计数值的操作。

内存管理示例

示例1

        OSG开发笔记(六):OSG内存管理_第4张图片

       因为添加的父节点grp已经是ref_ptr<>类型,所以goede没必要声明为osg::ref_ptr,将geode添加进grp父节点时,父节点(ref_ptr<>类型)会把子节点Geode的引用计数值置1。

       注意:但是尽管没有意义,为了养成习惯,建议都使用ref_ptr< >以保证 OSG 的内存管理工作正确

       以下为正确的代码,该代码减小内存开辟动作,虽效率高一点但是建议还是用上面的代码,不要省ref_ptr< >,避免给自己挖坑。

       OSG开发笔记(六):OSG内存管理_第5张图片

示例2

       下面代码会产生错误,编译时报析构函数为保护成员。

       

示例3

       ref_ptr< >类型的变量只能够指向派生自Referenced 的对象,或者与Referenced类有相同接口的对象(若不满足,编译器会报错误)。

       OSG开发笔记(六):OSG内存管理_第6张图片

示例4

        OSG开发笔记(六):OSG内存管理_第7张图片

 

总结

        将派生自 Referenced 的对象赋予 ref_ptr< >变量,这一动作将自动调用
Referenced::ref()并使引用计数加一。

  • 如果将ref_ptr< >变量指向其它的对象,或者将其释放,那么将调用
    Referenced::unref()方法,使引用计数减一。当计数器的值为0时,unref()
    自动释放对象所占用的内存空间。
  • 为新的 Referenced 对象开辟内存空间时,要尽量将其赋予ref_ptr< >,以保证 OSG 的内存管理工作正确。

 

参考资料

《OpenSceneGraph快速入门指导》


原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/95042433

你可能感兴趣的:(Qt开发专栏,OSG,OSG三维开发专栏)