2012-04-30 10 views
1

私はちょうどstd::listクラスのC++について気付いたことがあります。私は好奇心が強いです。簡単に言うと、リストのイテレータが動作する方法に関係します。次のコードを考えてみましょう:標準テンプレートライブラリリスト - 二重リンクまたは循環リンクされていますか?

std::list<int> alist; 
alist.push_back(0); 
alist.push_back(1); 
alist.push_back(2); 

明らかに、これで3つの整数要素を持つリストが作成されます。私は、リストの先頭にイテレータを定義し、以下のように、たとえば、最初の要素に含まれる値をプリントアウトするためにそれを使用することができます:私は穏やかに奇妙見つける何

std::list<int>::iterator iter = alist.begin(); 
std::cout << *iter << std::endl; // Prints "0" to stdout 

で、もし私は今デクリメントイテレータは、それは「周りのループ」と、リストの最後の要素を指して終わる:

--iter; 
std::cout << *iter << std::endl; // Prints "2" to stdout 

はおそらく二重リンクリストとして実装されています何かのために、この合理的な行動ですか?リストが循環的にリンクリストであった場合、私はイテレータと同様の動作を期待していますが、これはかなり奇妙です。

過去に使用したこのイテレーターの振る舞いには、実用的な用途はありますか?この行動に関連する問題がありますか?

は(ちなみに、これはGCC 4.7.0(MinGWの)で発生します。私は他のバージョンやコンパイラでそれをテストしていません。)

+0

それは私のために-1218668059を印刷しますhttp://ideone.com/3kpQf –

答えて

10

beginを超えて反復子をデクリメント未定義の動作を呼び出します。あなたが見ている動作は、偶然の可能性が非常に高いです(実際には、別のコンパイラで何が起きるかを見てください)here

これを確認したい場合は、GCCのlistの実装を見てください。通常、ソースは/usr/include/c++/4.x.y/bits/stl_list.hにあります。

+0

ありがとうございます。ソースを読むことは、物事をうまくクリアするのに役立ちました。 (ideoneへのリンクもありがとう - 以前は見たことがありません) – pmcs

+0

実際に私はいくつかの実装で、円を閉じる隠れノードの使用を見てきました。その*ガード*を使うことで、残りの操作を簡単に実装することができます。挿入/消去はリストの先頭と末尾を特別に指定する必要はなく、 'node-> last'と' nodeそれらが有効な*オブジェクト*を参照していることを知って - > next'(ただし、実装で呼び出されます)。 –

0

あなたが持っている "2"は定数2(alist.push_back(2);)だと思います。 あなたはプログラムがとても短くてシンプルだと思いますが、私は正しいのですか?これは、4.2.1のgccで発見された

* 
    * Second, a %list conceptually represented as 
    * @code 
    * A <---> B <---> C <---> D 
    * @endcode 
    * is actually circular; a link exists between A and D. The %list 
    * class holds (as its only data member) a private list::iterator 
    * pointing to @e D, not to @e A! To get to the head of the %list, 
    * we start at the tail and move forward by one. When this member 

1

はstl_list.hを見ると、私はこのコメントに気づきました。 @Oliがgcc 4.2.1で実装されたものであるため、@Oliが提供する答えは変わりません。私はその機能に頼ります

+0

コメントは、実装に関して少し誤解を招きます。そのバージョンのSTLでのリストの実装は、ポインタだけを保持するノードの基本型と、ノードの基底を拡張し、実際のデータを含むノードの実装を定義します。このリストには、ループをクローズするノードベースインスタンス(とくに 'end()'イテレータ)が格納されています。違いを生む詳細は、リストを閉じる* link *がデータを保持するノードになることができない、または最も単純なループを実行することが不可能であるということです。 –

関連する問題