2009-09-30 26 views
3

你好堆棧溢出,我有一個設計使用flyweight模式共享位圖對象之間共享位圖對象管理繪圖操作等,並集成在GUI庫。這是一個嵌入式設備,所以內存很貴。目前我已經用一個輕量級類的auto_ptr的std :: vector來完成一個工作實現,該類用於計算使用情況。我知道這是一個壞主意,可能會泄漏,所以我正在重寫這部分。我正在考慮使用boost :: shared_ptr。我的問題的關鍵是,如果沒有使用,我想要發佈的位圖。如果我有一個shared_ptr池,我最終將使用一次加載的位圖。我正在考慮使用shared_ptr :: use_count()來刪除位圖,如果use_count()== 1。但是文檔警告use_count()的生產代碼。基本上問題是隨着單個重物釋放的輕量級模式。你認爲有更好的方法來做到這一點?使用輕量級模式共享位圖對象之間的位圖

+1

不能使用std :: auto_ptr的一個標準集裝箱,因爲它們不支持複製語義(僅移動語義)。 – 2009-09-30 10:01:39

+0

我認爲STL真的缺乏ptr_containers。所有複製對於重對象都是低效的,並且最終在容器的析構函數中進行內存管理。 – piotr 2009-09-30 10:30:16

回答

6

您可以使用boost弱指針池,以便池不會計入所有權。

只有位圖對象具有提升共享指針,這樣他們才決定何時釋放位圖。

弱指針的池允許我們檢索已建成位圖:

當你創建一個位圖對象,你可以:

  • 得到從弱指針的共享指針,如果它不是空,

  • 或以其他方式加載新的位圖,從中創建一個新的共享指針並插入/替換池中的弱指針。

下面是一個使用地圖池中的某些示例代碼:

#include <boost/shared_ptr.hpp> 
#include <boost/weak_ptr.hpp> 
#include <map> 
#include <string> 
#include <iostream> 

// represents the bitmap data 
class Bitmap 
{ 
public : 
    Bitmap(std::string const& name) : name(name) 
    { 
     std::cout << "Bitmap " << name << std::endl ; 
    } 

    ~Bitmap() 
    { 
     std::cout << "~Bitmap " << name << std::endl ; 
    } 

    std::string name ; 
}; 

// the flyweight pool 
class Factory 
{ 
public : 

    typedef std::map< std::string , boost::weak_ptr<Bitmap> > Map ; 

    boost::shared_ptr<Bitmap> get(std::string const& what) 
    { 
     Map::iterator x = map.find(what); 

     // retrieve existing object from map's weak pointers 

     if(x != map.end()) 
     { 
      if(boost::shared_ptr<Bitmap> shared = x->second.lock()) 
      { 
       return shared ; 
      } 
     } 

     // populate or update the map 

     boost::shared_ptr<Bitmap> shared(new Bitmap(what)); 
     boost::weak_ptr<Bitmap> weak(shared); 
     map.insert(std::make_pair(what , weak)); 
     return shared ; 
    } 

private : 
    Map map ; 
}; 


int main(int argc, char** argv) 
{ 
    Factory f ; 

    // we try our flyweight bitmap factory ... 

    boost::shared_ptr<Bitmap> a = f.get("a"); 
    boost::shared_ptr<Bitmap> b = f.get("b"); 

    // a is not made again 
    boost::shared_ptr<Bitmap> a2 = f.get("a"); 

    a.reset(); 
    a2.reset(); 

    // a is destroyed before ------ 

    std::cout << "------" << std::endl ; 
} 
+0

我喜歡它。但我認爲更多描述會更好。 – 2009-09-30 10:04:49

+0

我認爲這是一個非常好的主意!我沒有想過以這種方式使用weak_ptrs。我目前正在使用use_count()並且似乎沒有泄漏。我會嘗試weak_ptr解決方案,看看它是否確實有效。 – piotr 2009-09-30 10:07:07

+0

好的,我試圖讓它更清晰 – 2009-09-30 10:21:49

0

shared_ptr的想法是它爲您管理對象的生命週期。您不必檢查使用次數。每個用戶都有一個shared_ptr,在刪除用戶時刪除shared_ptrs,並且當沒有更多用戶離開時,它將爲您刪除位圖。如果您需要調用特殊的例程來刪除位圖,並且不能在析構函數中執行該操作,則可以在創建時將特殊的刪除函數傳遞給shared_ptr。

+0

你錯過了有一個沉重的物體池的地方,如果一個shared_ptr仍然存在,使用後它不會被刪除。 – piotr 2009-09-30 10:07:56

+0

共享指針的集合可以有效地成爲池。這正是它們設計的目的,是對大對象的引用,當沒有任何東西被引用時,它們被共享並刪除一個對象。 – Kylotan 2009-09-30 15:13:50