2009-09-30 25 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