将 unordered_map 设置为 unordered_map 的值

Posted

技术标签:

【中文标题】将 unordered_map 设置为 unordered_map 的值【英文标题】:Setting unordered_map as value for unordered_map 【发布时间】:2020-02-19 15:20:02 【问题描述】:

所以我试图将 unordered_map 设置为另一个 unordered_map 的值。 现在我遇到的问题是我无法将值放入第二个 unordered_map。 我的代码如下所示。

  std::string postCode;
  std::string[] postCodeSource = new std::string1111,2222,3333,4444;
  std::unordered_map<std::string,unordered_map<int,Foo*>*> data;
  int k1=1234;//can be any number
  for(int i = 0; i < 4; i++)
    postCode = postCodeSource[i]
    if(data[postCode]==NULL) 
      data[postCode]=new std::unordered_map<int,Foo*>();
    
    data[postCode]->at(int(k1)) = new Foo(postCodeSource[i]);
  

类:

class Foo
  public:
  Foo();
  Foo(std::string postCode);
  std::string firstName,Customername,postCode;

Foo(std::string postCode); 是一个简单的复制构造函数。

现在,当我到达 data[lastPlz.getString()]-&gt;at(int(k1.customer)) = new Foo(&amp;k1); 时,我从 unordered_map 得到一个超出范围的异常,这是有道理的,因为 k1.customer 还没有对象! 在我更改代码之前,我创建并填充了一个看起来像这样的指针。

std::unordered_map<int,Foo*> kdnrMap
kdnrMap[k1.customer] = new Foo(&k1);

后来,我将 kdnrMap 添加到 data。 这将不再按我的意图工作,因为此方法需要一个完全填充的 kdnrMap 才能将其添加到 data 中,而我不能再这样做了。 p>

所以我正在寻求帮助以填充 kdnrMap 我已经尝试了几乎所有我现在能想到的东西。

【问题讨论】:

这里缺少很多代码。 minimal reproducible example 可能会让这个问题很容易解决。 Foo, Foo2;一个实际编译的最小示例。我们可能会从您的文字描述中挑出您的问题,但这不必要地复杂和模棱两可。只需编写一些简单的代码来演示您的问题。 请注意operator[]相当昂贵,除非确实需要多次使用,否则最好只使用一次。您作为您的地图似乎拥有数据的所有权,您最好使用智能指针。 顺便说一句,为什么需要将内部地图存储为指针?只是为了让你的代码更复杂、更容易出错? 那么你不仅让它更复杂而且更慢,因为会涉及另一个不必要的间接。猜猜std::unordered_map 将其数据存储在哪里? 【参考方案1】:

您实际上并不需要将内部映射存储为指针。让外部地图拥有内部地图,如下所示:

std::unordered_map<std::string,
   std::unordered_map<int, std::unique_ptr<Foo>>> data;
data[postCode][int(k1.Kundennr)] = new Foo(&k1);

我建议不要在这里使用原始指针,因为如果您替换内部映射中的值,内存泄漏的风险很高。使用std::unique_ptr 使得处理指针变得非常简单。

您的异常可能发生,因为unordered_map::at 要求该值包含您要求的键,以便检索对它正在映射的值的引用。如果您像我的示例中那样使用operator[],则如果找不到密钥,则映射将创建一个条目。

如果您仍然坚持将外部映射的值作为指向内部映射的指针,那么您可以添加如下元素:

std::unordered_map<int, Foo*> &inner = *data[postCode];
inner[int(k1.Kundennr)] = new Foo(&k1);

data[postCode]->operator[](int(k1.Kundennr)) = new Foo(&k1);

【讨论】:

谢谢! ->operator[] 完全符合我的要求。我可能对此不以为然,但我使用内部地图作为指针,因为我认为它会更快。我不确定我是否应该使用智能指针,我正在开发一个超过 20 年的程序,我们有很多原始指针,我被教导不要混合这两个 你的想法是错误的,如果你幸运的话它不会慢 如果您不能使用智能指针,请注意data[postCode][0] = new Foo() 如果您不检查同一键是否存在先前的条目,则可能会泄漏内存。总而言之,unordered_map 从 C++11 开始就存在了,所以如果你在旧代码中包含一个现代特性,你不妨好好做。 所有来自数据库的数据邮政编码(显然)不是唯一的。但是第二个迭代器是一个唯一的客户 ID,所以如果这只是被覆盖的可能性很小甚至不存在。仍然感谢您的建议!

以上是关于将 unordered_map 设置为 unordered_map 的值的主要内容,如果未能解决你的问题,请参考以下文章

unordered_map 的最坏情况是啥?

boost::unordered_map 中以结构为键的 boost 变体

自定义 unordered_map 的哈希函数

C++ 将所有元素从向量复制到 map / unordered_map 的最佳方法

插入 unordered_map 丢失了

c ++:无法将一对<int,MLine *>插入到unordered_map