web-dev-qa-db-ja.com

C ++イテレータは有害と見なされますか?

今日のBoostライブラリカンファレンスで、 Andrei Alexandresc 、本の著者であるModern C++ DesignとLokiC++ライブラリが、「Iterators Must Go」というタイトルの講演を行いました( ビデオ 、- スライド )イテレータが悪い理由について、彼はより良い解決策を持っていました。

プレゼンテーションのスライドを読んでみましたが、なかなかうまくいきませんでした。

  1. イテレータは悪いですか?
  2. 彼の後任は本当に良いですか?
  3. C++の実装者は彼のアイデアを取り入れますか?
47
Unknown

まず、あなたの質問に答えるために:

  1. いいえ。実際、私は 他の場所 イテレータはコンピュータサイエンスのこれまでで最も重要で基本的な概念であると主張しました。私は(アンドレイとは異なり)イテレータも直感的だと思います。
  2. はい、もちろんですが、それは驚くべきことではありません。
  3. うーん。 Boost.Range とC++ 0xを見てください–すでにそうではありませんか?

ここでのAndreiの大きな貢献は、イテレータの概念を完全に削除し、範囲を便利なラッパーとしてだけでなく、コア構造として見ることです。他の言語はすでにこれを行っています(Andreiの概念の多くは.NETのLINQまたはPythonのイテレータをエコーするだけです)が、それらはすべて出力範囲しか提供していません。 Andreiは、従来のイテレータカテゴリと同様に、さまざまなタイプの範囲について議論しています。

その観点から、彼がこれらのイテレータカテゴリの恣意性をあざけることから始めるのは奇妙です。

また、彼の例、特にファイルのコピーはオフになっていると思います。はい、イテレータバリアントは、1975年のコードよりも巨大な改善されています。複雑なブレーク条件を持つループをoneステートメントに減らします。彼がここで本当に問題にしているのは、構文だけです。失礼します。ここではC++について話しています–もちろん構文は醜いです。はい、ここで範囲を使用すると改善されますが、構文的にのみです。

また、Andreiのfindの実装はオフになっていると思います。彼が実際に定義しているのは、LINQからのDropUntil操作(名前付けは難しいです!)です。 find操作は、実際には1つまたは0の要素(またはイテレーター!)を返す必要があります。ここでイテレータを回避することは、値をコピーするのではなく直接変更したい場合があるため、私の意見では役に立ちません。ここで1要素の範囲を返すと、オーバーヘッドが追加されるだけで、メリットはありません。アンドレイのやり方は悪いです。なぜなら、メソッドの名前が間違っていて誤解を招くからです。

そうは言っても、私はほとんどすべての点でアンドレイに本質的に同意します。イテレータは、コンピュータサイエンスからの私のペットの概念ですが、確かに大きな構文上の負担であり、多くの範囲(特に無限のジェネレータ)は、イテレータなしで便利に実装できます(そして実装する必要があります)。

40
Konrad Rudolph

アンドレイは時々少し挑発的かもしれません。イテレータは合理的な概念であり、ビットがそうであるという意味で非常に基本的です。しかし、C++のほとんどのビットがブールではなく、より大きな型の一部であるように、ほとんどのイテレータは高レベルで処理する必要があります。アンドレイは、そうするための適切なレベルが範囲オブジェクトであることは正しいです。ただし、istream_iteratorセンチネルが示すように、すべての範囲がイテレータ範囲として適切に公開されているわけではありません。これは、人工的なエンドイテレータを作成するための単なるハックです。しかし、彼のアイデアが実装によって取り上げられることはないと思います。 C++ 1xはC99と同じくらい関連性があります。

4
MSalters
  1. 私たちのほとんどは、forループがstd :: vectorを反復処理するなど、よく知られているイディオムでそれらを簡単に使用します。開発者はそれを読み、何が起こっているのかを知っています。私たちの日常のコーディング生活では、イテレータは良くも悪くもありません。イテレータは単に「仕事を成し遂げるもの」です。
  2. おそらくそうだ。
  3. 私はそうは思いません。
4
Daniel Daranas
  1. いいえ、悪くはありません。実際、非常に賢いアイデアです。ただし、これらは理想的ではなく、イテレータの概念には改善の余地があります。

  2. イテレータを使用した実際の問題の数を解決します。たとえば、多くの場合、単一のコンテナから2つの別々のオブジェクト(イテレータ)をクエリし、それらを2つの別々のオブジェクトとしてアルゴリズムに渡すのは面倒です(エラーが発生しやすい)。単一のオブジェクトを渡さないのはなぜですか? std::pair<iterator, iterator>でさえ、操作しやすい大まかな範囲になります-2つではなく1つのオブジェクト。また、a range is an iteratorを検討することをお勧めします。それは実際、アンドレイが示唆していることです。ちなみに、これらの問題のいくつかは、 Boost.Range によってすでに解決されています。

  3. 私はそれが起こったと思いますが、それは革命ではなく、進化です。

3
mloskot

C++ 0xはすでに最初のステップを実行しています。

  • 右辺値参照は、コンテナを範囲として扱う際のいくつかの問題を解決します
  • 範囲の概念を含む範囲がコアライブラリに追加されました

イテレータ機能(イテレータカテゴリ、定数、右辺値のすべての組み合わせを考えてください)を失うことなく範囲に移行することは、特に無限で可変の範囲を考慮に入れる場合は困難です。

3
James Hopkin

私は彼に同意します。イテレータはほとんど範囲より劣っていて、「より良いもの」が取り上げられるかどうかはわかりません。

「善は最高の敵」は、いつものようにここで強く活躍しています。イテレータは便利でしっかりと固定されているため、範囲のような優れたものが妥当な時間内にイテレータに取って代わることができるかどうかを知るのは困難です。

3
Brian

アンドレイはD言語の隠されたマーケティングをしようとしているのではありませんか(現在彼はそれを使っています)...?

Andreiは、コンテナーは問題ないと述べていますが、イテレーターは醜く、直感的でなく、エラーが発生しやすく、危険であり、実装が困難です(この最後の1つはかなり真実のようです...)そしてC++には何がありますか... ?彼らは醜い/.../危険ではありませんか?しかし、私たちは喜んで彼らを受け入れ、彼らと一緒に暮らしています。

どちらを書くのがより直感的ですか?

for(auto i=foo.begin();i!=foo.end();++i)
    bar(*i);

または

for (auto r=foo.all(); !foo.empty(); foo.popFront())
        bar(r.front());

イテレータの概念は、範囲やその他のアイデアで補完できますが、それらには場所があり、置き換えられることはないと思います。

2
Anonymous

イテレータの横に範囲を使用する必要があると思います。つまり、回転方法ではなく、進化方法を選択する必要があります。

2
anon

私はアンドレイとコンラッドの両方と私自身に同意しません:-)

最も基本的な概念はイテレータではなくインターフェースであり、それは今日誰もが行うあらゆる作業で非常に明白です(これはすべて、クロスライブラリ、クロス言語、クロスコンパイラ、クロスOS、クロスプラットフォーム、クロスネームです)それ :-)

イテレータも範囲(ソースレベルの使用を除く)も、クリーンでシンプル、非侵入的または侵入的、非共有または共有、非一意または一意以外のものを提供しません:ポインタ!型付きデータへのクリーンなポインターは単純に普遍的であり、データを可変または不変にすることができます。すべてのインターフェースは、あらゆる種類のマシンとコンパイラーにやさしく、さらにはるかに安全で、イテレーターと範囲の使用法を実装の詳細に委ねながら、それに対する別のレベルの間接参照です。

その点で、IEnumerableとIQueryableは半分の「正しいこと」TMを実行しますが、反復の概念が明らかに劣っており、STLで実行できること、制御を保持することなどよりもはるかに劣っています(ただし、メタデータは優れています)したがって、より優れた、よりクリーンなモデル)。インターフェースを使用することで、必要な抽象化を構築でき、おそらく矛盾しますが、本質的には簡単です。最適で、実行時またはコンパイル時の中立的なデータ表現とコード(アルゴリズム、コンパイラー、VMなどに不可欠です) 。

「動的」/コンポーネントシステム用に「ランタイム」インライン化まで最適化することも可能です(HotSpot VMをねじ込みます:-)。その程度まで、1975年までの進歩は、相互運用業界の巨大なワークロードから明らかなように最小限です(どこにでもあります)。このサイト、独自のオープンテクノロジーの使用などを含めて、コンピュータサイエンスの理想主義では、このタイプのインターフェイス「作業」は存在しないはずです)。

1
rama-jka toti

他のAPIや関数と同様に、誤用すると識別が困難な多くの問題が発生する可能性があります。イテレータは多くのプロジェクトで使用されていますが、その特性に応じて必要なケアを常に維持しています。その使用の前に、それらの制限を十分に理解する必要があります。イテレータは、ユーザーが適切であれば非常に便利です。
この質問は関連しています:
イテレータが有効かどうかを確認する方法はありますか?
const_iteratorsよりもイテレータを優先する必要がありますか?

1
lsalamon
  1. 時々
  2. 多分
  3. ありそうもない、少なくとも何年もの間
1
PowerApp101

そのプレゼンテーションから私が見ることができる唯一の議論は範囲を定義できないことであり、c ++ 0xの「ステートメントの範囲」提案はとにかくその問題をある程度排除しているようです。イテレータを使用する必要があるかどうかについての議論ではないかもしれませんが、イテレータを使用する必要がある/使用すべきでない状況についてはどうでしょうか。

0
Stowelly

C++の実装者は、新しい非標準のパラダイムを実装することなく、C++ 0xの完全な機能サポートを完全に実現できると思います。

0
anon