c++ - 在无序映射中插入智能指针调用析构函数
问题描述
我正在制作一个引擎并处理材质的东西我有一个静态渲染器类存储一个static std::unordered_map<uint, Ref<Material>> m_Materials;
(材质及其 ID),它Ref
是使用下一个方法的共享指针:
template<typename T>
using Ref = std::shared_ptr<T>;
template<typename T, typename ... Args>
constexpr Ref<T> CreateRef(Args&& ... args) { return std::make_shared<T>(std::forward<Args>(args)...); }
template<typename T>
constexpr Ref<T> CreateRef(T* t) { return std::shared_ptr<T>(t); }
所以一个 Material 是一个简单的类,用一个 unsigned int (uint) 来存储它的 ID 和一个字符串来存储它的名字,并创建它们并存储它们,我在渲染器中有下一个静态函数:
Ref<Material> Renderer::CreateMaterialWithID(uint material_id, const std::string& name)
{
Ref<Material> mat = CreateRef<Material>(new Material(material_id, name));
std::pair<uint, Ref<Material>> mat_pair(material_id, mat);
m_Materials.insert(mat_pair);
return mat;
}
问题在于,由于某种原因,插入地图会调用材质析构函数,从而导致插入一个空的智能指针(尽管 ID 已正确插入)[material_id, empty]
。
现在,材质和创建的对似乎正确存储了材质的数据,所以我不知道为什么地图失败了。我还尝试插入作为初始化列表({material_id, mat}
),将材料创建为CreateRef<Material>(material_id, name)
(不带new
),并使用emplace
而不是,insert
但我总是得到相同的结果,我不明白为什么地图调用析构函数。
有人看出什么不对了吗?
解决方案
尝试调用insert_or_assign
;如果密钥已经存在,insert
则只会破坏您尝试插入的对象。举个例子
m_Materials[0];
m_Materials.insert({0, std::make_shared<Material>(name)});
将shared_ptr
被丢弃,因为第一个[0]
创建了一个nullptr
值,而插入稍后看到它并说“如果它已经存在就不要插入”。
m_Materials.insert_or_assign({0, std::make_shared<Material>(name)});
替换存储在那里的 nullptr ,就像
m_Materials[0]=std::make_shared<Material>(name);
顺便说一句,我对CreateRef
有两个重载非常谨慎,一个接受构造函数参数,另一个接受指针。这是混淆地图和领土的一个例子,我发现它在烦人的时候会在一个不舒服的地方咬你。
推荐阅读
- rust - 有没有办法在 Rust 中使用 avro-rs 序列化 JSON 值?
- javascript - 在javascript中的字符串内插入或使用变量
- regex - 使用 awk 提取所有电子邮件
- python - 在python中使用子进程找不到文件错误
- mysql - Mysql server 5.7 - 无法使用 mysql shell 'cluster.addInstance()' 添加新的集群实例
- typescript - 如何使用过滤器进行类型缩小?
- sql-server - 如果 where 子句不返回任何记录,则返回所有值
- excel - 访问vba以将excel中的公式复制到最后一行
- wso2 - WSO2 contentType text/html 与 axis2.xml 中的 application/xml 重叠
- javascript - 应该怎么做才能确保密钥不会保留在内存中?节点 Js