Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从shared_ptr ResourceManager释放资源_C++_Resource Management_Memory - Fatal编程技术网

C++ 如何从shared_ptr ResourceManager释放资源

C++ 如何从shared_ptr ResourceManager释放资源,c++,resource-management,memory,C++,Resource Management,Memory,我实现了一个简单的ResourceManager——在我尝试实现它的析构函数进行(紧急)清理(例如在发生致命异常的情况下)之前,一切都很好。我找不到一种方法来做这件事: template<typename T> class ResourceManager { public: std::unordered_map<std::string, std::weak_ptr<T> > resource_map; std::shared_p

我实现了一个简单的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_);
    }
};
模板
班级资源经理
{       
公众:
std::无序地图资源地图;
std::shared_ptr getResource(std::string name)
{
std::shared_ptr res=resource_map[name].lock();
如果(!res)
{
res=std::shared_ptr(新的T(这个,名字));
资源映射[名称]=res;
}
返回std::移动(res);
}
无效释放(标准::字符串名称)
{
资源映射擦除(名称);
};
~ResourceManager(无效){/*?????*/}
};
类纹理
{
私人:
资源经理*经理*;
std::字符串名称;
公众:
纹理(ResourceManager*管理器,标准::字符串和名称)
:经理,姓名{}
~Texture(void){
经理->发布(姓名);
}
};
显然,我必须迭代所有活动资源……但是如果ResourceManager不是资源的技术(唯一)所有者,我如何释放它们呢?这可能是设计上的缺陷,如果是这种情况,请建议替代方案。


编辑:为了响应回答,要定义“资源管理器”,我设想使用权威缓存存储对资源的引用,这些资源可以查找资源(=无重复项)并管理其在内存中的状态(在内存中,仅描述(=路径+类型)和释放),所有这些都尽可能自动化。(应该有单独的ResourceLoader,但这对这个问题没有太大的改变)

因此,您的代码在这里并没有对您的总体设计做太多说明,但是

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

如果希望资源管理器成为资源数据的权威所有者,则需要更改其设计/实现。例如,您可以让它将
shared_ptr
s存储到资源本身,而只将
weak_ptr
s发送到客户端。或者只需存储
unique_ptr
s并向客户机代码发送裸指针


但是,正如本文所述,您不需要(实际上也不能)做任何事情来清理
~ResourceManager()

中的资源,因此,您的代码在这里没有做很多事情来说明您的总体设计,但是

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

如果希望资源管理器成为资源数据的权威所有者,则需要更改其设计/实现。例如,您可以让它将
shared_ptr
s存储到资源本身,而只将
weak_ptr
s发送到客户端。或者只需存储
unique_ptr
s并向客户机代码发送裸指针


但正如本文所述,您不需要(实际上也不能)做任何事情来清理
~ResourceManager()

中的资源。要提出替代方案,我们需要知道您的资源管理器应该有什么用途

  • 您是否希望它作为“资源集合”发挥作用,即在资源被明确释放之前保持其活动状态
  • 或者您希望它成为一个“资源缓存”,使资源保持活动状态,直到它决定释放一些资源以释放内存为止
  • 或者,您真的希望它不让任何资源保持活动状态,而只是保留一个可能被其他资源保持活动状态的资源列表吗
  • <>记住,C++中的代码> SaldJypTr> /Cult>S不能像GC作品那样工作。也就是说,如果您销毁/重置某个对象的最后一个
    共享\u ptr
    ,则该对象将立即被删除,即使该对象存在
    弱\u ptr
    s


    因此,方法(1)和(2)非常有意义。(3) 然而,这正是您目前拥有的,只有很少有意义(如果有的话)。

    要提出替代方案,我们需要知道您的资源经理应该有什么目的

  • 您是否希望它作为“资源集合”发挥作用,即在资源被明确释放之前保持其活动状态
  • 或者您希望它成为一个“资源缓存”,使资源保持活动状态,直到它决定释放一些资源以释放内存为止
  • 或者,您真的希望它不让任何资源保持活动状态,而只是保留一个可能被其他资源保持活动状态的资源列表吗
  • <>记住,C++中的代码> SaldJypTr> /Cult>S不能像GC作品那样工作。也就是说,如果您销毁/重置某个对象的最后一个
    共享\u ptr
    ,则该对象将立即被删除,即使该对象存在
    弱\u ptr
    s


    因此,方法(1)和(2)非常有意义。(3) 然而,这是你目前拥有的,只有很少有意义(如果有的话)。

    好吧,如果我分发
    弱\u ptr
    ,每次我决定使用它时,我都必须检查资源是否在内存中,不是吗?这能以某种方式自动/同步吗?这样我就可以保持分发
    shared\u ptr
    s的优势了?(=不需要每次使用都检查,并且知道资源有多少活动用户?)是的,客户端必须锁定()弱指针。如果你想让客户端知道他们的指针是否死了,并使用集中所有权模型而不是共享所有权模型,那就真的没有办法避免检查。好吧,如果我分发
    弱\u ptr
    ,每次我决定使用它时,我都必须检查资源是否在内存中,不是吗?能以这样的方式自动/同步吗