在无序映射中插入智能指针调用析构函数
Inserting a Smart Pointer in a Unordered Map calls destructor
我正在制作引擎并处理 material 的东西我有一个静态渲染器 class 存储 static std::unordered_map<uint, Ref<Material>> m_Materials;
(material 及其 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 是一个简单的 class 构造,用一个无符号整数 (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;
}
问题是插入到映射中,出于某种原因,调用了material析构函数,导致插入了一个空的智能指针(尽管正确插入了ID)[material_id, empty]
.
现在,material 和创建的对似乎正确存储了 material 的数据,所以我不知道为什么地图失败了。我还尝试插入作为初始值设定项列表 ({material_id, mat}
),将 material 创建为 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
有两个重载,一个接受构造函数参数,另一个接受指针。这是一个混淆地图和领土的例子,我发现它在烦人的时候让你不舒服。
我正在制作引擎并处理 material 的东西我有一个静态渲染器 class 存储 static std::unordered_map<uint, Ref<Material>> m_Materials;
(material 及其 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 是一个简单的 class 构造,用一个无符号整数 (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;
}
问题是插入到映射中,出于某种原因,调用了material析构函数,导致插入了一个空的智能指针(尽管正确插入了ID)[material_id, empty]
.
现在,material 和创建的对似乎正确存储了 material 的数据,所以我不知道为什么地图失败了。我还尝试插入作为初始值设定项列表 ({material_id, mat}
),将 material 创建为 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
有两个重载,一个接受构造函数参数,另一个接受指针。这是一个混淆地图和领土的例子,我发现它在烦人的时候让你不舒服。