c++ - unordered_map 不起作用

标签 c++ visual-studio-2010 boost c++-standard-library

<分区>

我在 Visual C++ 16.0(Visual Studio 2010 附带的那个)中尝试了各种实现,但我遇到了 std::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.现在这确实有效,但我在其他地方遇到了另一个问题。虽然上面的代码相同,但相同的 key 不断被插入两次或更多次。为什么我的 map 无法管理最简单的事情并且每个键只保留一个条目?

我已经三次检查哈希函数和比较函数。我不认为他们应该为此负责。

我做错了什么?

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);
  }
};
}

最佳答案

原来是一个简单的共享内存问题。我不知不觉地没有考虑到我用来插入项目的内存来自一个临时变量。虽然一切都是保留在原地的堆内存,但实际键值(不是散列或存储桶位置)从一个条目到另一个条目发生了变化。进而导致上述不一致、不合逻辑的操作。

经验教训,当问题的性质不合逻辑时,问题的原因很可能在性质上是相似的。我只是将 CKey 中的 const char* m_Str 成员声明更改为 std::wstring m_Str 就完成了。

此修复使 CKey 结构变得相当小,这很好。将我原来的实现替换为这个效果很好。

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;
  }
};

关于c++ - unordered_map 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27289038/

相关文章:

c++ - 如何使用 Boost::Python 打印到 Python 终端

c++ - 在 std::vector<std::pair> 中查找

c++ - 在 C++ 中检测到堆损坏

c# - 您将所有解决方案级(全局)任务放在哪里?在专门为此目的的其他空项目中?

c++ - 多个类,相同的公共(public)接口(interface)

c++ - 从 C++ 中的结构访问单个成员类型的所有元素

c++ - CPP - 使用 * 或 and 返回地址

c++ - boost::combine() 是否与方法的输出一起使用?

C++ FFmpeg 刷新后如何继续编码?

c++ - 是否可以将功能卸载到显卡?