簡體   English   中英

C++ unordered_map 默認分配器

[英]C++ unordered_map default allocator

我有一個抽象的 class ( parent ),並且剛剛從中創建了派生 class ( child ),如下所示:

class parent {
public:
    virtual string print()=0;
};

template<class T>
class child: public parent{
private:
    unordered_map<string, parent*> children;
public:
    parent *&operator[](string name) {
        return children[name];
    }
    virtual string print(){
        //some jobs...
    }
}

好的。 現在我使用派生的 class 如下所示:

child<string> a;
a["test"]->print();

問題就出來了。

我認為問題在於 unordered_map::[] 運算符創建了我想要的class 而不是class 的實例。

如何告訴unordered_map創建新項目作為child < string >

假設您有一個std::unordered_map<std::string, int>並且您執行以下操作:

std::unordered_map<std::string, int> m;
std::cout << m["hello"];
std::cout << m["key1"];

上述程序不會產生任何警告或錯誤。 實際上,它將 output 00 兩個零。 那么,這里發生了什么?

unordered_mapmap operator[]插入一個值,以防鍵不存在。 這是 C++ 中無意錯誤的最大來源之一。 在上面的情況下, "hello""key1"不存在,所以它們是在原地創建的,默認value初始化為0

如何解決您的問題?

在使用operator[]之前,請務必確保您嘗試訪問的值是否存在。 事實上,如果要執行讀取,最好使用 .at .at()成員 function。

固定代碼:

child<string> a;
a["test"] = new child<string>;
a["test"]->print();

您可以通過更改您的operator[] function 來進一步防止這種行為:

    parent *&operator[](string name) {
        if (children.find(name) == children.end()) // does it exist?
            children[name] = new child<T>; // if it doesn't, create a new one.
        return children[name];
    }

unordered_map<std::string, parent *>::operator[]不會創建任何class 的實例,因為它的值是指針,而不是 class 實例。 因此,如果您使用它訪問之前未插入 map 的密鑰,它將默認初始化一個指針(將其初始化為 nullptr)並將其存儲在 map 中。

如果您想要 map 中的任何非 nullptr 值,您需要自己將它們存儲在那里。 你可以在你的operator[] function 中做到這一點:

parent *&operator[](string name) {
    auto &rv = children[name];
    if (!rv) rv = new child<T>;
    return rv;
}

如果您覆蓋任何這些通過引用返回的指針,那么這有泄漏 memory 的危險,而且您需要在析構函數中釋放它們。 您可以通過返回parent *而不是parent *&或在 map 中使用std::unique_ptr<parent>並在此處返回std::unique_ptr<parent> &來避免前一個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM