2016-12-01 4 views
1

私はこの簡単なテストプログラムを書いています。しかし、私はここで何が起こるのか理解できません。出力に奇妙なことがあるので:私はリストを印刷する場合リストエレメントが消去されると、イテレータの最後には何が起こりますか?

std::list<std::pair<double,double>> l; 
l.push_back({0.3,0.9}); 
l.push_back({-0.3,0.5}); 
l.push_back({0.3,0.7}); 
l.push_back({1.2,1.83}); 


for(auto it=l.begin(); it!=l.end(); ++it){ 
    double lx= it->first + 0.01; 
    double ly= it->second + 0.01; 

    it->first = lx; 
    it->second = ly; 

    if(lx < 0.0 || lx > 1.0 || ly < 0.0 || ly > 1.0){ 
    it = l.erase(it); 
} 

は、私が手:

0.32, 0.92 
0.31, 0.71 

なぜイテレータは(2回0.1)最初の要素に戻っていますか?

+1

ifの '== 0'は余計ですが、実際は' it!= end() 'がそれを処理するため、ifは役に立たないのです。なぜ私は最初の要素が2回あると言っているのか分かりません。あなたは1位と3位の要素を削除して、要素0と2を削除するように見えます。 – Borgleader

+0

答えをありがとう。はい、Element 0と2を出力しますが、最初の要素に0.1を2回追加します。私は理由を理解できません: (0.31、0.91)と(0.31,0.71) – Susliks

+0

これを行うための典型的なパターンは、l.erase(std: :remove_if(...)、l.end()) '。 – ArchbishopOfBanterbury

答えて

7
it=list.erase(it); 

これは、要素をitから消去します。次に、消去された要素がの後にイテレータの位置を返します。

forループが反復を終了すると、++を介してitに進み、end()に等しいかどうかを確認します。

ループが消去されるたびに、ループが両方の要素をスキップします。良くない。最後の要素を消去すると、それは最後のイテレータに進みます。これは不正です。

ループヘッダーforから++itを削除します。ループの最後に、itまたはitで消去してください。どちらも両方とも消去されません。

奇妙な印刷動作はUBによるものです。位置0のデータをインクリメントします。位置1のデータをインクリメントしてから削除します。位置2をスキップします。位置3のデータをインクリメントしてから削除します。最後のイテレータを過ぎて進む(未定義の動作)。その後、データの場所0と2を再度インクリメントするランダムな処理が行われます。推測すると、イテレータの末尾にある++は、特定のケースで最初の要素にループバックします(これはまったく保証されませんが、UBの何かが起こる可能性があります)。その後、2つ目のループが正常に実行され、2つの要素のデータがインクリメントされ、何も削除されません。

関連する問題