最近這幾天玩了一下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 "正在閱讀的你"有幫助,謝謝!!
沒有留言:
張貼留言