OSG:先導篇 內存管理

一.簡介

OSG提供了一種自動管理內存的機制,這種機制涉及到兩個類:osg::ref_ptr類  和 osg::Referenced類node

 

二.osg::Reference類

 osg::Reference類實現了對內存區段的引用計數器功能。數組

全部的OSG的節點和場景圖形數據(狀態信息 頂點數組 法線  紋理座標)都派生於Referenced類進行內存引用計數安全

 

Referenced類有3個主要組成部分:函數

1.保護成員整型變量_refCount,用做引用計數,在構造時被初始化爲0this

2.公有函數ref()和unref(),用於實現_refCount值得增長和減小,當_refCount爲0時,unref()將自動釋放該對象所佔用的內存spa

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對象的智能指針,並對其引用計數器進行管理code

osg::ref_ptr<>模板類包含了3個主要組成部分:server

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更安全。
相關文章
相關標籤/搜索