[英]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_map
或map
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.