C ++:在unordered_map中访问数据时设置

时间:2017-11-20 02:44:39

标签: c++ c++11 segmentation-fault set unordered-map

我定义了一个简单的结构EdgeList,它只是一个unordered_map,它将字符串键与set个字符串相关联。

class EdgeList{
private:
  std::unordered_map<std::string,std::set<std::string>> map;

public:
  EdgeList(){};

  void insert(std::string key,std::string item);

  std::set<std::string> operator[](std::string key);
};

void EdgeList::insert(std::string key,std::string item)
{
  if(map.count(key)==0) //key not already in map
  {
    std::set<string> newset;
    map.emplace(key,newset);
  }
  map[key].insert(item);
}

std::set<string> EdgeList::operator[](string key){
  return map[key];
}

EdgeList::insert只检查密钥是否已存在于unordered_map中(如果不存在则创建新集)并将该项插入关联集。 EdgeList::operator[]返回与输入键关联的集合。

这很简单,但当我尝试访问EdgeList中的数据时出现了问题。当我尝试像

这样的东西时,我一直在听到神秘的段错误
EdgeList el;
//populate el
string KeyInEdgeList;

for(auto it=el[KeyInEdgeList].begin();it!=el[KeyInEdgeList].end();++it)
{
  std::cout << *it << std::endl;
}

可能发生了什么?类定义中有错误吗?出于某种原因,我不能使用迭代器吗?在我的智慧结束时,这不应该是复杂的。

1 个答案:

答案 0 :(得分:0)

您的operator[]会返回一个值:

std::set<std::string> operator[](std::string key);
^^^^^^^^^^^^^^^^^^^^^

也就是说,每次调用此函数时,都会从基础映射中复制一个新的std::set,然后在表达式结束时将其销毁。换句话说:

for(auto it=el[KeyInEdgeList].begin();it!=el[KeyInEdgeList].end();++it)
//          |--- 1st set ---|             |--- 2nd set ---|

这是两个不同的 set,这两个都会在您实际取消引用迭代器时被破坏。在for循环的主体内,您有一个悬空引用。

您要做的是让operator[]返回引用,然后,无论如何,使用基于范围的内容:

for (std::string const& elem : el[KeyInEdgeList]) { ... }