使用多态类的std :: unique_ptr作为std :: unordered map

时间:2017-04-12 12:38:49

标签: c++ unique-ptr unordered-map

我的问题来自一个我应该完成的项目。我必须创建一个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是很好的。造成撞车的原因是什么?除崩溃发生之外,调试器不提供任何信息。

如果需要有关该项目的更多信息,请指出。感谢您阅读

0 个答案:

没有答案