32

少し離れて古いメロンを払い落とそうとした後、C++に戻ります。

hasNext()Java では、 Iterator は、 、 、next()およびのメソッドを持つコンテナーへのインターフェースremove()です。の存在は、通過するコンテナの制限の概念を持っているhasNext()ことを意味します。

//with an Iterator
Iterator<String> iter = trees.iterator();
while (iter.hasNext()) 
{
    System.out.println(iter.next());
}

C++ 標準テンプレート ライブラリでは、イテレータはサポートするデータ型またはクラスを表しているように見えますが、制限の概念が組み込まれていないoperator++ためoperator==、次の項目に進む前に比較が必要です。通常の場合、2 番目のイテレーターがコンテナーの終了である場合、2 つのイテレーターを比較するユーザーが制限をチェックする必要があります。

vector<int> vec;
vector<int>::iterator iter;

// Add some elements to vector
v.push_back(1);
v.push_back(4);
v.push_back(8);

for (iter= v.begin(); iter != v.end(); iter++)
{
    cout << *i << " "; //Should output 1 4 8
}

ここで興味深いのは、C++ ではポインターが配列への反復子であることです。STL は既存のものを採用し、その周りに慣例を構築しました。

私が見逃しているこれ以上の微妙な点はありますか?

4

9 に答える 9

23

おそらくもう少し理論的です。数学的には、C++ のコレクションは、イテレータの半分開いた間隔として記述できます。つまり、1 つのイテレータがコレクションの先頭を指し、1 つのイテレータが最後の要素のすぐ後ろを指します。

この慣習は多くの可能性を開きます。アルゴリズムが C++ で機能するように、それらはすべて、より大きなコレクションのサブシーケンスに適用できます。このようなことを Java で機能させるには、別の反復子を返す既存のコレクションのラッパーを作成する必要があります。

イテレータのもう 1 つの重要な側面については、すでに Frank が言及しています。イテレータにはさまざまな概念があります。Java イテレータは、C++ の入力イテレータに対応します。つまり、一度に 1 ステップだけインクリメントでき、後戻りできない読み取り専用のイテレータです。

反対に、C++ のランダム アクセス反復子の概念に正確に対応する C ポインターがあります。

全体として、C++ は、C ポインターや Java イテレーターよりもはるかに豊富で純粋な概念を提供し、さまざまなタスクに適用できます。

于 2008-09-11T12:29:48.810 に答える
21

はい、大きな概念上の違いがあります。C++ は、反復子のさまざまな「クラス」を利用します。一部はランダム アクセスに使用され (Java とは異なり)、一部はフォワード アクセスに使用されます (Java のように)。他のものでさえ、データの書き込みに使用されます(たとえば、で使用するためtransform)。

C++ ドキュメントのイテレータの概念を参照してください。

  • 入力反復子
  • 出力反復子
  • 前方反復子
  • 双方向反復子
  • ランダム アクセス反復子

これらは、Java/C# のちっぽけな反復子と比較して、はるかに興味深く強力です。これらの規則が C++0x のConceptsを使用して成文化されることを願っています。

于 2008-09-11T12:05:12.083 に答える
12

前述のように、Java と C# の反復子は、位置 (状態) と範囲 (値) の混合を記述しますが、C++ の反復子は、位置と範囲の概念を分離します。C++ の反復子は、「今どこにいるのか」と「どこに行けばいいのか」を別々に表します。

Java と C# の反復子はコピーできません。以前の位置を回復することはできません。一般的な C++ イテレータで可能です。

この例を考えてみましょう:

// for each element in vec
for(iter a = vec.begin(); a != vec.end(); ++a){
  // critical step!  We will revisit 'a' later.
  iter cur = a; 
  unsigned i = 0;
  // print 3 elements
  for(; cur != vec.end() && i < 3; ++cur, ++i){
      cout << *cur << " ";
  }
  cout << "\n";
}

上記のリンクをクリックして、プログラムの出力を表示します。

このかなりばかげたループは、シーケンスを通過し (前方イテレータ セマンティクスのみを使用)、3 つの要素の連続する各サブシーケンスを 1 回だけ出力します (そして最後にいくつかの短いサブシーケンスを出力します)。ただし、N 要素、および 3 ではなく 1 行あたり M 要素であると仮定すると、このアルゴリズムは依然として O(N*M) イテレータのインクリメントと O(1) スペースになります。

Java スタイルの反復子には、位置を個別に格納する機能がありません。あなたはどちらかになります

  • O(1) スペースを失い、(たとえば) サイズ M の配列を使用して、反復時に履歴を保存します
  • リストを N 回トラバースする必要があり、O(N^2+N*M) 時間になります
  • または、GetAt メンバー関数で具体的な配列型を使用すると、ジェネリック性とリンク リスト コンテナー型を使用する機能が失われます。

この例では前方反復メカニズムのみが使用されているため、問題なくリストをスワップできました。これは、検索、初期化と評価の遅延、並べ替えなどの一般的なアルゴリズムを作成する場合に重要です。

状態を保持できないことは、ほとんどアルゴリズムが構築されていない C++ STL 入力反復子に最も密接に対応しています。

于 2008-10-02T08:58:34.707 に答える
8

配列要素へのポインターは、実際には配列への反復子です。

あなたが言うように、Java では、反復子は C++ よりも基礎となるコンテナーについてより多くの知識を持っています。C++ イテレータは一般的であり、イテレータのペアは任意の範囲を表すことができます。これは、コンテナのサブ範囲、複数のコンテナにわたる範囲にすることができます ( http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdfを参照)。またはhttp://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html ) または数値の範囲 ( http://www.boost.org/doc/libs/1_36_0を参照) /libs/iterator/doc/counting_iterator.html )

イテレータのカテゴリは、特定のイテレータでできることとできないことを識別します。

于 2008-09-11T12:23:54.377 に答える
3

私にとっての根本的な違いは、Java イテレーターがアイテム間を指しているのに対し、C++ STL イテレーターはアイテムを指していることです。

于 2008-09-11T15:01:01.847 に答える
2

C ++イテレータは、ポインタの概念を一般化したものです。それらはそれをより広い範囲の状況に適用可能にします。これは、任意の範囲を定義するなどの目的で使用できることを意味します。

Javaイテレータは比較的ダムな列挙子です(C#ほど悪くはありませんが、少なくともJavaにはListIteratorがあり、コレクションを変更するために使用できます)。

于 2008-09-12T10:48:59.277 に答える
2

違いについては良い答えがたくさんありますが、Java イテレーターで最も気になる点が強調されていないと感じました。現在の値を複数回読み取ることはできません。これは多くのシナリオで、特に反復子をマージする場合に非常に役立ちます。

C++ には、反復子を進めて現在の値を読み取るメソッドがあります。その値を読み取っても反復は進みません。何度でも読めるように。これは Java イテレーターでは不可能であり、これを行うラッパーを作成することになります。

補足: ラッパーを作成する簡単な方法の 1 つは、Guavaの既存のPeekingIteratorを使用することです。

于 2015-04-29T21:18:40.073 に答える
1

C ++ライブラリ(以前はSTLと呼ばれていた部分)イテレータは、ポインタと互換性があるように設計されています。Javaは、ポインター演算を使用せずに、プログラマーにとってより使いやすい自由を持っていました。

C ++では、イテレータのペアを使用する必要があります。Javaでは、イテレータまたはコレクションのいずれかを使用します。イテレータは、アルゴリズムとデータ構造の間の接着剤であると想定されています。1.5以降用に記述されたコードは、特定のアルゴリズムまたはデータ構造を実装している場合を除いて、イテレータについて言及する必要はほとんどありません(プログラマーの大多数が行う必要はありません)。Javaは動的ポリモーフィズムのサブセットなどを採用しているため、処理がはるかに簡単です。

于 2008-09-11T12:41:53.413 に答える
1

イテレータは、配列の内容を順番に繰り返し処理する単純なケースでのみポインタと同等です。イテレータは、データベース、ファイル、ネットワーク、その他の計算など、さまざまなソースからオブジェクトを提供できます。

于 2008-09-11T12:20:26.337 に答える