osg::observer_ptr和osg::ref_ptr用法与区别

       OSG是使用C++语言开发的,而该语言在动态内存管理方面做得并不好,经常需要程序员手动申请和释放内存。这种靠人工管理内存的方式不仅繁琐,而且极易造成内存泄漏,尤其在一个中大型系统中,靠人工管理内存是一项艰巨的任务。    

        数据类型osg::ref_ptr(智能指针)在源码中随处可见,它和另外一种数据类型osg::observer_ptr(观察指针)为我们提供了非常良好的动态对象使用体验。

1.智能指针的用法

osg::Node* pNode = new osg::Node();
osg::ref_ptr<osg::Node> rpNode=pNode;
if(rpNode.valid())
{  

rpNode-> ...

}

       通过osg::Node实例化一个智能指针模板对象rpNode,该对象可以直接保存一个使用new关键字动态创建的osg::Node对象,并可通过valid() 方法判断内部对象是否有效。

       使用->操作符直接对内部对象进行调用,这里无需关心osg::Node对象的释放,因为在智能指针对象rpNode析构时会自动检查是否需要删除对象,如果需要则直接删除。

2.观察指针的用法

osg::Node* pNode = new osg::Node();
osg::observer_ptr<osg::Node> opNode=pNode;
if(opNode.valid())
{

opNode-> ...

}

        osg::observer_ptr与osg::ref_ptr的用法基本相同,不同的是osg::observer_ptr不负责对象的释放,这也是为什么叫它观察指针的原因,可理解为只观察不管理。

       所以,上面代码如果没有其他osg::ref_ptr智能指针对创建的osg::Node对象进行管理,将造成内存泄漏,该对象将不会自动释放。

      可通过osg::observer_ptr对象的lock方法,将观察指针转为智能指针,代码如下:

osg::Node* pNode = new osg::Node();
osg::observer_ptr<osg::Node> opNode=pNode;
osg::ref_ptr<osg::Node> pRefNode;
if(opNode.valid())
{
    opNode->lock(pRefNode); // 将观察指针转为智能指针
}

3.实现原理

     osg::ref_ptr和osg::observer_ptr是两个模板类,而用于实例化该模板类的类型必须从osg::Referenced继承。OSG中大多数类型都是从该类继承而来的,它才是实现内存自动管理的核心所在。

      osg::Referenced类最主要的功能是内部维护了一个引用计数_refCount,并提供了ref()和unref()函数来负责该引用计数的递增和递减。在unref()函数中,当_refCount递减为0值时会自动释放该对象占用的内存。

     有了osg::Referenced类的支持,对于osg::ref_ptr而言其实只需要做两件事:

    1)在着手管理一个对象时调用该对象的ref()方法增加其引用计数。

    2)当不在管理该对象时调用该对象的unref()方法减少其引用计数。

osg::observer_ptr的实现正如它的名字一样,是通过一种简单的“观察者”设计模式来实现的。osg::Referenced内部维护了一个观察者列表,并且在引用计数递减为0时主动通知所有的观察者对象,每一个osg::observer_ptr对象都是一个观察者。

    对于osg:: observer _ptr而言需要做以下三件事:

    1)在开始观察一个对象时将自己加入到该对象的观察者列表中;

    2)在停止观察对象时将自己从该对象的观察者列表中移除;

    3)收到观察者通知时,将内部观察的对象设置为无效。

关系如下:

 通过下表,我们来体会一下OSG中对象的创建和释放的过程,以及在这当中智能指针与观察指针的作用,引用计数的变化情况等。

       每一个osg::ref_ptr对象都占有一个被引用对象的引用计数,在正常情况下只要最后一个osg::ref_ptr还在使用,被它引用的对象就不会释放。所以osg::ref_ptr可用于需要长期使用并保证一个对象可用的情况。

      osg::observer_ptr 作为对象的观察者,最大的作用就是可以在访问其观察的对象时,判断该对象是否已经被销毁了。它只是尝试性的使用,不对观察对象产生任何影响,观察的对象随时可能被释放,所以应该经常使用valid()方法判断其有效性。

      通过以上介绍,相信大家对OSG的智能指针和观察指针都有了一定程度的理解,并且可以在不同场景下做到正确使用。

 本文作者:恒歌科技

地址:OSG基础之内存管理-恒歌科技 (henggetec.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值