我的问题来自一个我应该完成的项目。我必须创建一个std::unordered_map<T, unsigned int>
,其中T是指向基类多态类的指针。过了一段时间,我认为使用std::unique_ptr<T>
作为关键字也是一个好习惯,因为我的地图是为了拥有这些对象。让我介绍一些背景故事:
将具有多态 sell_obj 的类层次结构视为基类。从该类继承的预订和表。我们现在知道我们需要创建一个std::unordered_map<std::unique_ptr<sell_obj*>, unsigned int>
。因此,从该映射中删除一对将自动释放键指向的内存。整个想法是让钥匙指向书籍/桌子,这些钥匙的价值将代表我们商店所包含的产品数量。
在处理std::unordered_map
时,我们应该为所有三个类指定哈希值。为简化起见,我在 main 中指定了它们:
namespace std{
template <> struct hash<book>{
size_t operator()(const book& b) const
{
return 1; // simplified
}
};
template <> struct hash<table>{
size_t operator()(const table& b) const
{
return 2; // simplified
}
};
// The standard provides a specilization so that std::hash<unique_ptr<T>> is the same as std::hash<T*>.
template <> struct hash<sell_obj*>{
size_t operator()(const sell_obj *s) const
{
const book *b_p = dynamic_cast<const book*>(s);
if(b_p != nullptr) return std::hash<book>()(*b_p);
else{
const table *t_p = static_cast<const table*>(s);
return std::hash<table>()(*t_p);
}
}
};
}
现在让我们看一下地图的实现。我们有一个名为 Shop 的课程,如下所示:
#include "sell_obj.h"
#include "book.h"
#include "table.h"
#include <unordered_map>
#include <memory>
class Shop
{
public:
Shop();
void add_sell_obj(sell_obj&);
void remove_sell_obj(sell_obj&);
private:
std::unordered_map<std::unique_ptr<sell_obj>, unsigned int> storeroom;
};
并实现两个关键功能:
void Shop::add_sell_obj(sell_obj& s_o)
{
std::unique_ptr<sell_obj> n_ptr(&s_o);
storeroom[std::move(n_ptr)]++;
}
void Shop::remove_sell_obj(sell_obj& s_o)
{
std::unique_ptr<sell_obj> n_ptr(&s_o);
auto target = storeroom.find(std::move(n_ptr));
if(target != storeroom.end() && target->second > 0) target->second--;
}
在我的 main 中,我尝试运行以下代码:
int main()
{
book *b1 = new book("foo", "bar", 10);
sell_obj *ptr = b1;
Shop S_H;
S_H.add_sell_obj(*ptr); // works fine I guess
S_H.remove_sell_obj(*ptr); // usually (not always) crashes [SIGSEGV]
return 0;
}
我的问题是 - 我的逻辑失败在哪里?我听说自从C ++ 11以来在STL包含器中使用std::unique_ptr
是很好的。造成撞车的原因是什么?除崩溃发生之外,调试器不提供任何信息。
如果需要有关该项目的更多信息,请指出。感谢您阅读