首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >unordered_map不工作

unordered_map不工作
EN

Stack Overflow用户
提问于 2014-12-04 16:07:53
回答 1查看 1.6K关注 0票数 0

我已经尝试了Visual Studio16.0( Visual Studio2010附带的)中的各种实现,我发现std::unordered_map有各种各样的错误

例如

代码语言:javascript
复制
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。现在,这确实起作用了,但我在其他地方有另一个问题。上面的代码是一样的,但是相同的key会被插入两次或更多。为什么我的map不能管理最简单的事情,并且每个键只保留一个条目?

我已经三次检查了哈希函数和比较函数。我不认为这是他们的错。

我做错了什么?

m_Records的类型为boost::unordered_map<CKey, CRecord*>std::unordered_map<CKey, CRecord*>

CKey是这样定义的:

代码语言:javascript
复制
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);
  }
};
}
EN

回答 1

Stack Overflow用户

发布于 2014-12-05 16:50:43

事实证明,这个问题是一个简单的共享内存问题。我在不知不觉中没有考虑到我用来插入项的内存来自于一个临时变量。虽然所有内容都是保留在原地的堆内存,但实际的键值(而不是散列或存储桶位置)会随着条目的不同而变化。这反过来导致了上述不一致和不合逻辑的操作。

当问题的性质是不合逻辑的时,问题的原因很可能在性质上是相似的。我简单地将CKey中的const char* m_Str成员声明更改为std::wstring m_Str,就这样做了。

修复使CKey结构变得相当小,这很好。用我原来的实现来代替它工作得很好。

代码语言:javascript
复制
struct CKey
{
  std::wstring m_Str;

  CKey(const wchar_t* s)
    : m_Str(s)
  {
  }

  size_t hash() const
  {
    if (!this->m_Str.empty())
    {
      char temp[16];
      memset(temp, 0, sizeof(temp));
      MurmurHash3_x64_128(this->m_Str.c_str(), (int)sizeof(wchar_t) * (int)this->m_Str.size(), 0, temp);
      size_t hash = *(size_t*)temp;
      return hash;
    }
    return 0;
  }

  bool operator==(const CKey& other) const
  {
    return this->m_Str.compare(other.m_Str) == 0;
  }
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27289038

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档