我有std::map<const char*, std::shared_ptr<Resource, ResourceDeleter>>
,其作用类似于ResourceDatabase。当有人请求std::map
中已有的资源时,会插入std::map
中的项目(否则将从std::map
投放)。同样,当不再使用资源时,应将其删除。在ResourceDeleter
中,我将从std::map
中删除记录。问题是永远不会调用ResourceDeleter
,因为std::shared_ptr
中仍有一个std::map
。将项目插入std::map
后,将始终有2个std::shared_ptr
- 一个用于需要资源的代码,另一个用于std::map
。删除第一个std::shared_ptr
后,我需要从std::map
删除资源。
答案 0 :(得分:2)
您应该在std :: map中使用std::weak_ptr。
#include <iostream>
#include <memory>
struct A {
std::string hello() { return "hello"; }
~A() { std::cout << "Destructor ~A() called" << std::endl; }
};
void use(std::weak_ptr<A> const& wp)
{
if (auto spt = wp.lock())
{
std::cout << "Accessing object... " << spt->hello() << "\n";
}
else
{
std::cout << "use(): object was deleted\n";
}
}
int main()
{
std::weak_ptr<A> wp;
{
std::shared_ptr<A> sp = std::make_shared<A>();
wp = sp;
use(wp);
std::cout << "Destructing sp" << std::endl;
}
use(wp);
std::cout << "Destructing wp" << std::endl;
}
输出:
访问对象...你好 破坏sp
析构函数~A()称为
use():对象被删除
破坏wp
答案 1 :(得分:1)
我理解这个问题,目标是当删除最后一个指向资源的共享指针时,应该从ResourceMap中删除资源然后删除。正如您所说,如果资源的共享指针保留在ResourceMap中,则无法工作,因为映射中的共享指针始终是资源的最后一个共享指针。
所以有两个简单的解决方案。一种是在Map中保留一个弱指针(std::weak_ptr
)到资源。另一个可能更简单的解决方案是在ResourceMap中保留资源本身。在这两种情况下,您都需要包装std::map
(或std::unordered_map
),因为您需要返回一个指向Resource的共享指针,该指针不是关联容器的mapped_type
。
资源可以使用map
直接构建到map::emplace
。
实际上实现ResourceDeleter并不简单,因为要进行删除,您需要访问映射和键(或者值的迭代器)。
为了减少shared_ptr的大小,我考虑将shared_pointer的对象作为迭代器或指向std::pair<const key_type, mapped_type>
的指针。然后你需要一个智能指针周围的包装器,这样*
运算符最终将被实现为p->second
而不是*p
。