1

std::listC++のクラスについて気になる点があることに気付きました。簡単に言えば、リストのイテレータが機能する方法に関するものです。次のコードを検討してください。

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) で発生します。他のバージョンやコンパイラではテストしていません。)

4

3 に答える 3

10

それを超えて反復子をデクリメントすると、begin未定義の動作が呼び出されます。あなたが目にしている振る舞いは偶然の一致である可能性が非常に高いです (実際、別のコンパイラで何が起こるかはこちらを参照してください)。

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

于 2012-04-30T00:29:27.553 に答える
1

stl_list.h を見て、次のコメントに気付きました。

   *
   *  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

これは 4.2.1 gcc で見つかりました。これは、gcc 4.2.1 で実装されたものであるため、@Oli によって提供される回答を変更しません。私はその機能を頼りにします

于 2012-04-30T00:53:36.587 に答える
0

あなたが得た "2" は定数 2(in alist.push_back(2);) だと思います。あなたのプログラムはとても短くてシンプルだと思いますが、そうですか?

于 2012-04-30T00:46:38.253 に答える