c++ - 共享对象工厂 - 更新 weak_ptr 映射
问题描述
我有一个场景,许多对象可能需要加载一些资源,但是当资源的路径相同时,应该共享资源对象。以下简化代码呈现了上述概念:
struct Obj
{
};
struct SharedObjects
{
std::shared_ptr<Obj> CreateObj(const std::string& key)
{
auto itr = registry_.find(key);
if(itr != registry_.end())
{
return itr->second.lock();
}
auto obj = std::make_shared<Obj>();
registry_[key] = obj;
return obj;
}
void ObjRemoved(const std::string& key)
{
auto itr = registry_.find(key);
if(itr != registry_.end())
{
if(!itr->second.use_count())
{
registry_.erase(itr);
}
}
}
private:
std::unordered_map<std::string, std::weak_ptr<Obj>> registry_;
};
int main()
{
SharedObjects sharedObjects;
auto p1 = sharedObjects.CreateObj("a");
auto p2 = sharedObjects.CreateObj("b");
auto p3 = sharedObjects.CreateObj("a");
p2.reset();
sharedObjects.ObjRemoved("b");
}
我想知道如何改进更新 weak_ptr 地图?正如你现在看到的,我调用了 reset 和 ObjRemoved 函数。你有什么想法 ?(也许我应该使用一些设计模式)。您在代码中看到任何其他可以改进的地方吗?
Edit1 这是可能的解决方案:
可以从 Obj dtor 中删除空的 weak_ptr:
struct Obj
{
Obj::Obj(std::function<void()> clb): clb_(std::move(clb))
{}
Obj::~Obj()
{
clb_();
}
private:
std::function<void()> clb_;
};
修改 CreateObj 函数(ObjRemoved 函数被移除):
std::shared_ptr<Obj> SharedObjects::CreateObj(const std::string& key)
{
auto itr = registry_.find(key);
if(itr != registry_.end())
{
return itr->second.lock();
}
auto obj = std::make_shared<Obj>([this, key]
{
registry_.erase(key);
});
registry_[key] = obj;
return obj;
}
Edit2 没有智能指针的替代解决方案:
struct Obj
{
};
struct SharedObj
{
Obj* CreateObj(const std::string& key)
{
auto itr = registry.find(key);
if(itr != registry.end())
{
++(itr->second.refCount);
return &itr->second.obj;
}
auto& objRecord = registry[key] = ObjRecord{};
return &objRecord.obj;
}
void RemoveObj(const std::string& key)
{
auto itr = registry.find(key);
if (itr != registry.end())
{
auto& refCount = itr->second.refCount;
--refCount;
if (refCount == 0)
{
registry.erase(itr);
}
}
}
private:
struct ObjRecord
{
Obj obj;
std::uint16_t refCount{1};
};
std::unordered_map<std::string, ObjRecord> registry;
};
解决方案
推荐阅读
- php - 单个列过滤(选择输入)可变
- android - 如何在 C# 上使用预览为 android 创建 PDF 查看器
- python - 检查数字是否在给定范围内:未能按指示打印消息
- r - 不是散点图中的所有值
- html - 在另一个组件Angular 7中绑定ngModel上的值
- facebook-graph-api - 如何以编程方式在 DNN 标头标签中包含元标签?
- python - 如何使用 PyLucene 从所有索引文档中检索特定字段?
- http - 如何将 http 服务调用返回的值绑定到 Angular6 中 UI 中的字段下拉列表
- vb.net - 如何减少pdf中嵌入的重复字体
- c - 在 C 中测量没有 pthread 的开销