OSG:先导篇 内存管理

一.简介

OSG提供了一种自动管理内存的机制,这种机制涉及到两个类:osg::ref_ptr类  和 osg::Referenced类

二.osg::Reference类

 osg::Reference类实现了对内存区段的引用计数器功能。

所有的OSG的节点和场景图形数据(状态信息 顶点数组 法线  纹理坐标)都派生于Referenced类进行内存引用计数

Referenced类有3个主要组成部分:

1.保护成员整型变量_refCount,用作引用计数,在构造时被初始化为0

2.公有函数ref()和unref(),用于实现_refCount值得增加和减少,当_refCount为0时,unref()将自动释放该对象所占用的内存

3.作为保护成员存在的虚析构函数

1.类定义

class OSG_EXPORT Referenced
{
public:
  Referenced();
  explicit Referenced(bool threadSafeRefUnref);
  Referenced(const Referenced&);
  inline Referenced& operator = (const Referenced&) {return *this;}
  virtual void setThreadSafeRefUnref(bool threadSafe);

#if defined (_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  bool getThreadSafeRefUnref() const {return true;}
#else
  bool getThreadSafeRefUnref() const {return _refMutex != 0;}
#endif

#if defined (_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  OpenThreads::Mutex* getRefMutex() const {return getGlobalReferencedMutex();}
#else 
  OpenThreads::

}

三.osg::ref_ptr类

osg::ref_ptr类用于实现一个指向Referenced对象的智能指针,并对其引用计数器进行管理

osg::ref_ptr<>模板类包含了3个主要组成部分:

1.一个私有指针_ptr,用于保存管理内存区域的地址,可以用get()方法返回_ptr的值

2.类似指针重载定义了方法

3.valid()方法,用于判断ref_ptr<>是否为空,不为NULL时返回true

 osg::ref_ptr<osg::类> 对象 = new osg::类;

 

1.类定义

template<class T>

class ref_ptr
{
public:
typedef T element_type;

ref_ptr() : _ptr(0) {}
ref_ptr(T* ptr) : _ptr(ptr) {if(_ptr) _ptr->ref();}
ref_ptr(const ref_ptr& rp) : _ptr(rp.ptr) {if(_ptr) _ptr->ref();}
template<class Other> ref_ptr(const ref_ptr<Other>& rp) : _ptr(rp._ptr) {if(_ptr) _ptr->ref();}
ref_ptr(observer_ptr<T>& optr) : _ptr(0) {optr.lock(*this);}
~ref_ptr() {if(_ptr) _ptr->unref(); _ptr = 0;}

ref_ptr& operator = (const ref_ptr& rp)
{
assign(rp);
return *this;
}

template<class Other> ref_ptr& operator = (const ref_ptr<Other>& rp)
{
assign(rp);
return *this;
}

inline ref_ptr& operator = (T* ptr)
{
if (_ptr==ptr) return *this;
T* tmp_ptr = _ptr;
_ptr = ptr;
if (_ptr) _ptr->ref();
if(tmp_ptr) tmp_ptr->unref();
return *this;
}

#ifdef OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION
operator T*() const {return _ptr;}
#else

bool operator == (const ref_ptr& rp) const {return (_ptr == rp._ptr);}
bool operator == (const T* ptr) const {return (_ptr == ptr);}
friend bool operator == (const T* ptr, const ref_ptr& rp) {return (ptr == rp.ptr)}

bool operator != (const ref_ptr& rp) const {return (_ptr != rp._ptr);}
bool operator != (const T* ptr) const {return (_ptr != ptr);}
friend bool operator != (const T* ptr, const ref_ptr& rp) {return (ptr != rp._ptr);}

bool operator < (const ref_ptr& rp) const {return (_ptr < rp._ptr);}

private:
typedef T* ref_ptr::*unspecified_bool _type;

public:
operator unspecified_bool_type() const {return valid() ? &ref_ptr::_ptr : 0;}
#endif

T& operator* () const {return *_ptr;}
T* operator->() const {return _ptr;}

//获取指针
T* get() const {return _ptr;}

bool operator !() const {return _ptr == 0;}
bool valid() const {return _ptr != 0;}

//返回指针
T* release() {T* tmp = _ptr; if (_ptr) _ptr->unref_nodelete(); _ptr = 0; return tmp;}

void swap(ref_ptr& rp) {T* tmp = _ptr; _ptr = rp._ptr; rp._ptr = tmp;}

private:

template<class Other> void assign(const ref_ptr<Other>& rp)
{
if (_ptr == rp._ptr) return;
T* tmp_ptr = _ptr;
_ptr = rp._ptr;
if (_ptr) _ptr->ref();
if (tmp_ptr) tmp_ptr->unref();
}

template<class Other> friend class ref_ptr;
T* _ptr; };

2.使用 osg::ref_ptr<>

osg::ref_ptr<osg::Geode> geodePtr = new osg::Geode();
osg::Geode* obj1 = * geodePtr;       //获取Geode指针
osg::Geode* obj2 = geodePtr.get();  //获取Geode指针

//作为返回值
osg::Geode* createGeode()
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
return geode.release();
}

四.使用智能指针

在osg中,大多数场景图形类都继承自osg::Reference,但也有注意的地方

1.使用智能指针模板的类必须继承自osg::Reference类,否则无法使用

2.在创建智能指针之后,不能手动调动delete来删除该智能指针,否则编译会提示错误信息。因为osg::Reference的析构函数是保护类型

3.在osg::Reference类成员函数中,有两个共有的成员函数ref() 和 unref(),它们主要是用来控制内存计数器,不要随意使用来改变内存计数器的值

4.在osg中,可以new运算指针

每个类要使用之前先用智能指针托管,用于避免内存泄漏

bool CPickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{

  osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Geode> node1 = new osg::Geode;
osg::ref_ptr<osg::Geometry> geo1 = new osg::Geometry;

root->addChild(node1.get());
node1->addDrawable(geo1.get());
printf("%d, %d, %d", root->referenceCount(), node1->referenceCount(), geo1->referenceCount());
}

五.dynamic_cast

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
原文地址:https://www.cnblogs.com/k5bg/p/11451170.html