OSG提供了一種自動管理內存的機制,這種機制涉及到兩個類:osg::ref_ptr類 和 osg::Referenced類node
osg::Reference類實現了對內存區段的引用計數器功能。數組
全部的OSG的節點和場景圖形數據(狀態信息 頂點數組 法線 紋理座標)都派生於Referenced類進行內存引用計數安全
Referenced類有3個主要組成部分:函數
1.保護成員整型變量_refCount,用做引用計數,在構造時被初始化爲0this
2.公有函數ref()和unref(),用於實現_refCount值得增長和減小,當_refCount爲0時,unref()將自動釋放該對象所佔用的內存spa
3.做爲保護成員存在的虛析構函數指針
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類用於實現一個指向Referenced對象的智能指針,並對其引用計數器進行管理code
osg::ref_ptr<>模板類包含了3個主要組成部分:server
1.一個私有指針_ptr,用於保存管理內存區域的地址,能夠用get()方法返回_ptr的值對象
2.相似指針重載定義了方法
3.valid()方法,用於判斷ref_ptr<>是否爲空,不爲NULL時返回true
osg::ref_ptr<osg::類> 對象 = new osg::類;
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; };
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和static_cast的效果是同樣的;在進行下行轉換時,dynamic_cast具備類型檢查的功能,比static_cast更安全。