我試圖在Visual C++ 16.0各種實現方式(一個附帶的Visual Studio 2010),我讓所有類型的bug與std::unordered_map
unordered_map不起作用
例如
CKey key = pszName;
auto it = m_Records.find(key);
if (it != m_Records.end())
{
// we replace existing item (so delete old)
delete it->second;
it->second = pRecord;
}
else
{
const size_t sz = m_Records.size();
m_Records.insert(std::make_pair(key, pRecord));
const size_t sz2 = m_Records.size();
assert((sz + 1) == sz2); // this assertion fails! wtf!
}
m_Records
是一個std :: unordered_map實例。所以我切換到boost::unordered_map
1.48。現在,這確實有用,但我在其他地方有另一個問題雖然上面的代碼相同,但是相同的密鑰不斷插入兩次或更多次。我的地圖如何管理最簡單的事情,並且每個密鑰只保留一個條目?
我有三倍檢查哈希函數和比較函數。我不相信他們應該責怪在這裏。
我在做什麼錯?
m_Records
的類型是boost::unordered_map<CKey, CRecord*>
或std::unordered_map<CKey, CRecord*>
。
CKey
被定義爲這樣:
struct CKey
{
const wchar_t* m_Str;
int m_Len;
CKey(const wchar_t* s)
: m_Str(s)
, m_Len(s ? (int)wcslen(s) : 0)
{
}
size_t hash() const
{
if (this->m_Len > 0)
{
char temp[16];
memset(temp, 0, sizeof(temp));
MurmurHash3_x64_128(this->m_Str, (int)sizeof(wchar_t) * this->m_Len, 0, temp);
size_t hash = *(size_t*)temp;
return hash;
}
return 0;
}
bool operator==(const CKey& other) const
{
if ((this->m_Len > 0) & (this->m_Len == other.m_Len))
{
return (wcscmp(this->m_Str, other.m_Str) == 0);
}
// otherwise, they are only equal if they are both empty
return (this->m_Len == 0) & (other.m_Len == 0);
}
};
namespace boost
{
template <>
struct hash<CKey>
{
size_t operator()(const CKey& k) const
{
return k.hash();
}
};
}
namespace std
{
template <>
struct equal_to<CKey>
{
bool operator()(const CKey& x, const CKey& y) const
{
return (x == y);
}
};
}
調試器在斷言失敗時說什麼是關鍵有趣的呢?密鑰可能在地圖中發生變異? (也就是說,它們是否包含指向其他人指向的資源的指針?)您可以生成一個MCVE嗎?什麼版本的'boost'? – Yakk 2014-12-04 08:15:32
它全是單線程的,沒有併發性,所以在插入或任何映射操作發生時,我看不出有什麼變化。 – 2014-12-04 08:16:42
不是,鑰匙在地圖中的全部時間,而不僅僅是當您調用地圖方法時。意外地在地圖(有序或無序)中變換鍵是常見的'哎呀',導致UB和意想不到的奇怪。密鑰在存儲時必須是不可變的哈希和比較。沒有更多的細節,只是在黑暗中刺傷。 – Yakk 2014-12-04 08:21:37