最近這幾天玩了一下Boost::SmartPointer,感覺還不錯用,順手寫了些Sample Code,主要的內容是說:一各ResourceManager要如何精確管理Resource?確定Resource何時可以被release?換句話說,Resource在出生後傳遞給外界被使用,參考來參考去,Manager必須知道Resource到底已經被參考過幾次了,到這第一各想法就是Smart Pointer,藉由Smart Pointer本身的Reference Count即可解決問題所在。
當然我也是第一次使用SmartPointer,所以爬文少不了,對岸網友在一各論壇上寫了篇還不錯的教學,對新手來說相當有用可以看看:
http://www.usidcbbs.com/read-htm-tid-1978.html
國外這篇發表在stackoverflow的也不錯:
http://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when-should-i-use-one
【附帶一提】
Manager會把有Resource的第一各Ref_Count,所以當Resource被Manager第一次產生時 or 不在有外界使用時,Ref_Count == 1,這樣的好處是Manager在檢查當Ref_Count == 1的時候可以清楚的知道Resource接下來是因該被刪除還是再保留一段時間後刪除,有就是Resource cache system的作用,如果沒記錯OGRE也是使用類似的做法。
來看Sample Code吧:
#include < iostream > #include < map > #include "shared_ptr.hpp" #include "shared_array.hpp" class Object { public: Object( int iID ) : m_iID(iID) {} virtual ~Object( void ) { m_iID = -1; } int getID( void ) { return m_iID; } protected: int m_iID; }; typedef boost::shared_ptr ObjectPtr; class ObjectManager { typedef std::map ObjectsMap; public: ObjectManager( void ) : m_mapObjectPtrs() {} virtual ~ObjectManager( void ) { // Check object's ref_count, if anyone is not 1, assert!! ObjectsMap::iterator ite; ObjectsMap::iterator iteEnd = m_mapObjectPtrs.end(); for( ite=m_mapObjectPtrs.begin(); ite!=iteEnd; ++ite ) { int iRefCount = ite->second.use_count(); if( iRefCount != 1 ) { std::cout << std::endl; std::cout << "WARRING: Object ID: " << ite->second->getID() << "Ref_count is not 1" << std::endl; assert( iRefCount == 1 ); } } } ObjectPtr getObj( int iID ) { ObjectsMap::iterator ite = m_mapObjectPtrs.find( iID ); if( ite == m_mapObjectPtrs.end() ) { m_mapObjectPtrs.insert( ObjectsMap::value_type( iID, ObjectPtr(new Object(iID)) ) ); ite = m_mapObjectPtrs.find( iID ); } return ite->second; } protected: ObjectsMap m_mapObjectPtrs; }; void testFunCallByValue( ObjectPtr spObj ) { std::cout << "spObj ID: " << spObj->getID() << " Ref_count: " << spObj.use_count() << std::endl; } void testFunCallByReference( ObjectPtr& spObj ) { std::cout << "spObj ID: " << spObj->getID() << " Ref_count: " << spObj.use_count() << std::endl; } void testFunCallByPointer( ObjectPtr* spObj ) { std::cout << "spObj ID: " << (*spObj)->getID() << " Ref_count: " << (*spObj).use_count() << std::endl; } void testFunSharedArray( void ) { // New object array which doesn't have default constructor; void* pObjectMemory = operator new[]( sizeof(Object)*5 ); Object* pObjArray = static_cast<Object*> ( pObjectMemory ); for( int i=0; i<5; i++ ) new (&pObjArray[i])Object(i); // shared_array sample code: // all Objects will be managed by one shared_array boost::shared_array spaObjArray( pObjArray ); std::cout << "shared_array Ref_count: " << spaObjArray.use_count() << std::endl; // shared_array will delete ObjectArray automatically!! // No need delete[] pObjectMemory; } void main( void ) { // Create instance of ObjectManager: ObjectManager* pObj_manager = new ObjectManager();; // Get Object from Manager: ObjectPtr spObj = pObj_manager->getObj(5); std::cout << "spObj ID: " << spObj->getID() << " Ref_count: " << spObj.use_count() << std::endl; // Testing functions: testFunCallByValue( spObj ); //Ref_Count will +1 testFunCallByReference( spObj ); //Ref_Count will +0 testFunCallByPointer( &spObj ); //Ref_Count will +0 testFunSharedArray(); // Release Object: spObj.reset(); if( spObj == NULL ) std::cout << "spObj == NULL" << std::endl; // Get another Object from Manager: spObj = pObj_manager->getObj(2); std::cout << "spObj ID: " << spObj->getID() << " Ref_count: " << spObj.use_count() << std::endl; // Delete manager: delete pObj_manager; pObj_manager = NULL; return; }
以上的說明希望對"未來的我" or "正在閱讀的你"有幫助,謝謝!!
沒有留言:
張貼留言