2013-02-01 9 views
10

は、このコードをチェックしてください:std :: list :: clearはstd :: list :: endイテレータを無効にしますか?

#include "stdafx.h" 
#include <list> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::list<int> mylist; 
    mylist.push_back(1); 
    std::list<int>::iterator i = mylist.end(); 
    if(i == mylist.end()) 
     printf("end is end\n"); 

    mylist.clear(); 
    if(i == mylist.end()) 
     printf("never get here because Microsoft seems to " 
       "think the iterator is no longer safe.\n"); 

    return 0; 
} 

さて、cplusplus.comによると、これは問題になることはありませんし、リリースモードでは、私は、これは結構ですと、本当にすべての問題が発生しないと思いますが、デバッグのように不可能になりますこれは私を続行させずにうわべだけ。すべてのポインタ?

+0

興味深い。私は '.end'も無効になったと思っていましたが、その記事は反対です。興味深いことに、http://ideone.com/Y338N8が期待どおりに実行されます。 +1 –

+0

私はWindowsに移植しようとしているコードがMacOSとLinuxを対象に書かれていたので、完璧な意味があります。どちらもGCCを実行しています。私はこれが図書館のバグだと思う。 –

答えて

10

その他の回答は、一般的に、コンテナがクリアされたときに有効なコンテナの過去と最後のイテレータには依存できないと指摘しています。しかし、リストの過去・エンドイテレータは確かに有効なままにしてください:

C++ 11の23.3.5.4/3 効果:が消去要素にのみイテレータと参照を無効にします。

過去のイテレータはどの要素も参照していないため、無効化しないでください。

+0

+1、私の答えを削除しました。以前の会話から、動的に割り当てられたセントリを使用することは、標準で明示的にサポートされていることを思い出していますが、これは 'clear()'がそれを解放する必要があるという意味ではありません。 'clear()'は 'erase(begin()、end())'として実装され、 'end()'イテレータは無効になりません。これは、実装にバグとしてMicrosoftに報告する必要があります。 –

+2

ありがとう、マイクと@DavidRodríguez-dribeas。はい、これはVisual C++ 2012の 'std :: list'実装のバグです。これはVisual C++ 2010の回帰です。「消去」も同様に壊れています。私はこのバグの修正を数ヶ月前にチェックしました。この修正は、Visual C++標準ライブラリの次回リリース版に現れます。この修正により 'erase'と' clear'の両方が修正されました。 (このバグは顧客から報告されましたが、Microsoft Connect経由では報告されませんでしたので、私が参照できるリンクはありません) –

+1

Microsoftに報告されましたが、VS2013:http://connect.microsoft。 com/VisualStudio/feedback/details/808659/std-list-t-erase-in-debug-mode-invalidates-end-iterator – Macker

-2

これは実際には無効です。 イテレータは現在の状態コンテナでのみ有効です。 アイテムを追加または削除すると、イテレータは無効になります。

あなたがリンクしている記事は、あなたがしていることが有効であるとは言えません。彼らはクリア後に新しいイテレータを取得します。

リリースコードに表示されない理由は、問題を解決するデバッグが無効になっているためです。 C++ 11から

+0

さらにもう一度: "このイテレータを除いて、このコンテナに関連するすべてのイテレータ、リファレンス、ポインタは無効になります。 –

+0

@meh:いいえ、間違っています。最後のイテレータ*を無効にすることができます –

+3

"アイテムを追加または削除すると、イテレータは無効になります。"それは一般的には当てはまりません。各コンテナはそれ自身の無効化規則を持ち、 'list'イテレータは参照する要素がまだリストに入っている限り有効です。 –

4

、表100(シーケンスコンテナ要件):

clear() [...]過去エンドイテレータを無効にしてもよいです。

そしてstd::listもちろんシーケンスコンテナテンプレート(23.3.5.1/2)である:リスト内の2つの表に与えられる可逆容器(の容器の要件のすべてを満たす

23.2)、配列コンテナの(ほとんどのオプションのコンテナコンテナ要件(23.2.3)およびアロケータ対応コンテナ(表99)を含む)例外は演算子[]とメンバー関数であり、提供されていません。ここでは、これらのテーブルのいずれかに記載されていないリストに対する操作、または追加の意味情報がある操作についてのみ説明します。

+0

これに加えるには、 'end'イテレータは特異値ですイテレータの安定性を保証するほとんどのノードベースコンテナは、非特異的な値に対してのみこれを保証します。 –

+1

私は、「それがない過去のイテレータとコンテナを無効にするコンテナがある」と読めるべきだと思います。そうでなければ、競合する仕様となるでしょう。 –

+1

しかし、リスト固有の仕様書23.3.5.4/3には、「イテレータとイレースされた要素への参照のみを無効にします**」と書かれています。 –

関連する問題