2017-11-20 34 views
0

単純な構造のEdgeListを定義しました。文字列のsetと単純にunordered_mapが関連付けられています。C++:unordered_mapでデータにアクセスして設定するときのsegfault

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

何が起こっているのですか?クラス定義に間違いがありますか?何らかの理由でイテレータを使用できないのですか?私はウィットの終わりにいますが、これは複雑ではありません。

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

新しいstd::setが基礎となるマップからその式の最後に破棄されますこの関数を呼び出すたびに、コピーされ、次のとおりです。

+0

'のstd :: map'の'演算子[] '[作成:範囲ベースのために何があなたのoperator[]参照を返し、その後、かかわらず、使用していされてやりたい

キーが存在しない場合はこれを参照してください(http://en.cppreference.com/w/cpp/container/map/operator_at)ので、 'insert(string、string)'の 'if'文は冗長です。同様の理由から、 'for'ループでは、' operator [] 'で空のセットを作成し、ループ内の空のセットでイテレータを逆参照しようとします。 – cantordust

答えて

0

あなたoperator[]は値を返します。言い換えれば:

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

あなたのイテレータを逆参照実際の時間によって破壊されますどちらも2つの異なるset S、だこと。 forループの本体内には、参照がありません。

for (std::string const& elem : el[KeyInEdgeList]) { ... } 
関連する問題