如何从shared_ptr ResourceManager中释放资源

时间:2015-01-29 22:51:27

标签: c++ resource-management memory

我实现了一个简单的ResourceManager - 一切都很好,直到我尝试为(紧急)清理实现其析构函数(例如在致命异常的情况下)。我无法找到一种方法:

template<typename T>
class ResourceManager
{       
public: 
    std::unordered_map<std::string, std::weak_ptr<T> > resource_map;
    std::shared_ptr<T> getResource(std::string name) 
    {
        std::shared_ptr<T> res = resource_map[name].lock();
        if(!res)
        {
            res = std::shared_ptr<T>(new T(this, name));
            resource_map[name] = res;
        }
        return std::move(res);
    }

    void Release(std::string name)
    {
        resource_map.erase(name);
    };
    ~ResourceManager(void) { /* ???? */}
};

class Texture
{
private:
    ResourceManager<Texture> * manager_;
    std::string name_;

public:
    Texture(ResourceManager<Texture> * manager, std::string& name) 
          : manager_(manager), name_(name) { }
    ~Texture(void){ 
        manager_->Release(name_);
    }
};

显然,我必须迭代所有活动资源......但是如果ResourceManager不是技术上(唯一)资源所有者,我如何释放它们?这可能是设计的缺陷,如果是这种情况,请建议替代方案。

编辑:响应答案,定义“资源管理器”我想象权威缓存 - 存储用于引用资源(可以查找资源(=无重复))并管理它们在内存中的状态(内存中) ,仅描述(=路径+类型)和释放),以上所有内容尽可能自动化。 (应该有单独的ResourceLoaders,但这个问题没有太大变化)

2 个答案:

答案 0 :(得分:2)

所以,你的代码并没有做很多事情来阐明你的整体设计,在这里,但是 ......

实施后,您的资源管理器似乎只有指向资源的弱指针。这表明它不对实际资源本身的生命周期负责,因此不应该在其析构函数中清理这些资源。

如果您希望资源管理器成为资源数据的权威所有者,那么您将需要更改其设计/实现。例如,您可以将shared_ptr存储到资源本身,并仅将weak_ptr传递给客户端。或者只是存储unique_ptr并传出指向客户端代码的指针。

但正如所写,你不需要(并且实际上不能)做任何事情来清理~ResourceManager()中的资源。

答案 1 :(得分:2)

为了建议替代方案,我们需要知道资源管理器应该具有的目的。

  1. 您是否希望它作为“资源集合”运行,即在资源明确发布之前保持资源的存在?
  2. 或者你是否希望它成为一个“资源缓存”,保持资源存活,直到它决定释放一些资源以释放内存?
  3. 或者您是否真的希望它不会保留任何资源,只需保留一份可能由其他东西保存的资源列表?
  4. 请记住,C ++中的shared_ptr不能像GC一样工作。即如果您销毁/重置最后一个shared_ptr对象,该对象将立即删除,即使它有weak_ptr

    所以方法(1)和(2)可以很有意义。 (3)然而,这是你现在拥有的,很少有意义(如果有的话)。