2011-10-21 46 views
2

我有在我的遊戲明星級的,我希望他們使用質地所以我想出了這個代碼一樣...使用靜態指針到類的內存管理?

sf::Texture* Star::starTexture = NULL; 
unsigned int Star::refCount = 0; 

Star::Star() : starSpeed(0), starScale(0), locX(0), locY(0) 
{ 
    if (starTexture == NULL) 
    { 
     starTexture = new sf::Texture(); 
    } 

    refCount++; 
} 

Star::~Star() 
{ 
    refCount--; 

    if (refCount == 0) 
    { 
     delete starTexture; 
     starTexture = NULL; 
    } 
} 

我使用的星級這樣的.. 。

for (int i = 0; i < STAR_COUNT; ++i) 
{ 
    Star star; 

    star.Initialize(/* blah blah */); 

    starVector.push_back(star); 
} 

我是「高級C++技術」的新手,我很擔心這不起作用。我是否需要定義一個拷貝構造函數?矢量會弄亂我的參考計數嗎?我願意提供更好的方法來提供這方面的建議。我想我可以保持紋理以外的類,並通過一個參考,當我初始化每個星,但我喜歡留在類內的紋理...

+0

爲什麼要添加引用次數的compilcations。爲什麼不是sf :: Texture Star :: starTexture;讓棧疊加應變? –

回答

5

是的,它會搞砸,如果你沒有明確定義copy constructorcopy assignment operator爲你上課。

vector這樣的STL容器有copy-by-value語義。當Star對象被複制到vector時,其中的原始指針被複制。所以你現在有多個指針指向一個單獨的內存,這絕對會讓你處於未定義行爲的快速軌道上。

你應該做的是明確定義這些函數。手動執行該內存的深度複製並正確增加您的參考計數。

一個更好的方法是在你的類內部保存一個類似於boost::shared_ptrstd::tr1::shared_ptr的RAII對象,讓它自動爲你處理資源管理(包括重新計數的東西)。那麼你不需要明確定義這些函數了。

class Star 
{ 
.. 
private: 
    std::tr1::shared_ptr<sf::Texture> m_starTexture; 
}; 

// link the smart pointer w/ resource 
Star::Star(): m_starTexture(new Texture()) 
{ 
    ... 
} 

這是保證通過語言功能的工作:

  1. 當你的對象被複制,非靜態成員對象的複印功能被稱爲
  2. 當您的對象被刪除時,非靜態成員對象的析構函數被稱爲

在這種情況下,智能指針的複印功能將相應地增加引用計數,而 析構函數會遞減引用計數,並解除分配資源,如果引用計數等於0

+0

謝謝!我的記憶暗示了這一點,但它太微弱了...... – replicant

+0

謝謝!然而,我對std :: tr1 :: shared_ptr有些困惑,Class Star的每個實例是否都可以訪問相同的紋理,或者每個新星都會創建一個新的紋理?我可以在頭文件中聲明靜態shared_ptr嗎? – replicant

+0

這取決於。當你創建一個新的明星對象時,它會在其構造函數中創建一個新的紋理。所以如果你創建了10個啓動對象(堆棧或堆),它們裏面有10個不同的紋理。但是,當您將星形對象(例如,複製到矢量或另一個星形對象)複製時,這些對象將共享相同的紋理。不要爲shared_ptr使用靜態。 –