50

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

プレゼンテーションのスライドを読もうとしましたが、あまり理解できませんでした。

  1. イテレータは悪いですか?
  2. 彼の代わりは本当に良いですか?
  3. C++ の実装者は彼のアイデアを採用するでしょうか?
4

13 に答える 13

41

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

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

ここでの Andrei の大きな貢献は、イテレータの概念を完全に削除し、範囲を単なる便利なラッパーとしてではなく、コア コンストラクトとして見なすことです。他の言語はすでにこれを行っています (Andrei の概念の多くは .NET の LINQ または Python のイテレータを反映しているだけです) が、それらはすべて出力範囲のみを提供します。Andrei は、従来のイテレータ カテゴリと同様に、さまざまな種類の範囲を主張しています。

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

また、彼の例、特にファイルのコピーが間違っていると思います: はい、イテレータ バリアントは1975 年のコードから大幅に改善されています複雑なブレーク条件を持つループを1 つのステートメントに減らします。ここで彼が実際に問題にしているのは、単なる構文です。すみません、ここでは C++ について話しているのですが、もちろん構文は醜いです。はい、ここで範囲を使用すると改善されますが、構文的にのみです。

findAndreiの実装もオフだと思います。彼が実際に定義しているのは、DropUntilLINQ からの操作 (命名が難しい!) です。操作は、find実際には 1 つまたはゼロの要素 (またはイテレータ!) を返す必要があります。ここで反復子を避けることは、値をコピーする代わりに直接変更したい場合があるため、私の意見では役に立ちません。ここで 1 要素の範囲を返すと、オーバーヘッドが増えるだけでメリットはありません。メソッドの名前が間違っていて誤解を招くため、アンドレイのやり方は悪いです。

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

于 2009-05-08T09:24:05.097 に答える
4

Andrei は、少し挑発的なこともあります。イテレータは妥当な概念であり、ビットという意味で非常に基本的です。しかし、C++ のほとんどのビットが bool ではなく、より大きな型の一部であるように、ほとんどの反復子は高レベルで処理する必要があります。そうするのに適切なレベルは範囲オブジェクトであるという Andrei の意見は正しいです。ただし、istream_iterator 標識が示すように、すべての範囲が反復子範囲として適切に公開されるわけではありません。これは、人為的な終了イテレータを作成するための単なるハックです。ただし、彼のアイデアが実装に反映されるとは思いません。C++1x は C99 と同じくらい関連性があります。

于 2009-05-08T10:44:25.963 に答える
4
  1. 私たちのほとんどは、std::vector を反復する for ループのように、よく知られている慣用句でそれらを簡単に使用しています。開発者はそれを読み、何が起こっているかを知っています。私たちの日常のコーディング生活では、反復子は良いものでも悪いものでもなく、「仕事を成し遂げるもの」にすぎません。
  2. おそらくそうだ。
  3. 私はそうは思わない。
于 2009-05-08T09:49:37.157 に答える
4

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

「善は最善の敵である」というのは、いつものようにここでも強く作用しています。イテレータは便利でしっかりと定着しているため、レンジのようなより優れたものが合理的な時間内にそれらに取って代わることができるかどうかを知ることは困難です。

于 2009-05-08T08:21:49.317 に答える
3

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

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

イテレータの機能 (イテレータ カテゴリ、const-ness、rvalue-ness のすべての組み合わせを考えてください) を失うことなく範囲に移行することは困難です。

于 2009-05-08T09:31:56.903 に答える
3
  1. いいえ、それらは悪くありません。実際、非常に賢いアイデアです。ただし、それらは理想的ではなく、反復子の概念には改善の余地があります。

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

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

于 2010-01-25T23:59:05.397 に答える
2

Andrei は D 言語の隠れたマーケティングをしようとしているのではありませんか (現在彼は D 言語で作業しています)...?

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

どちらがより直感的に書くことができますか:

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

また

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

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

于 2009-05-12T06:53:35.487 に答える
2

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

于 2009-05-08T09:27:47.460 に答える
1

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

于 2009-05-08T13:21:10.557 に答える
1

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

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

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

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

「動的」/コンポーネント システムから「実行時」インライン化まで最適化することも可能です (スクリュー HotSpot VM:-). その範囲では、1975 年への進歩は最小限に抑えられており、これは巨大な相互運用業界のワークロードによって明らかです (それはどこにでもあります)。このサイト、プロプライエタリでオープンな技術の使用などを含めて見てください; コンピューターサイエンスの理想主義では、この種のインターフェース「作業」は存在すべきではありません..

于 2009-05-08T18:49:26.897 に答える
1
  1. 時々
  2. おそらく
  3. ありそうもない、少なくとも何年もの間
于 2009-05-08T08:37:56.907 に答える
0

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

于 2009-05-08T10:54:53.070 に答える
0

C++ の実装者は、新しい非標準のパラダイムを実装することなく、C++0x の完全な動作サポートを作成することに手一杯になると思います。

于 2009-05-08T08:29:37.380 に答える