52

MSDN は次のように述べています

swapiter_swap下位互換性のために C++ 標準に含まれていた よりも優先して使用する必要があります。

しかし、comp.std.c++ は次のように述べています。

ほとんどの STL アルゴリズムは反復子の範囲で動作します。したがって、これらの範囲内の要素を交換するときに使用するのは理にかなっていiter_swapます。これは、2 つの反復子が指す要素を交換するという意図された目的であるためです。これにより、 などのノードベースのシーケンスを最適化できますstd::list。これにより、データが実際にスワップされるのではなく、ノードが再リンクされるだけです。

それで、どれが正しいですか?iter_swapを使用する必要がありますか、または使用する必要がありますswapか? (iter_swap下位互換性のためだけですか?) なぜですか?

4

6 に答える 6

33

iter_swap標準自体には、次のことについての言及はほとんどありません。

  • の効果があるはずですが、swap(*a, *b)そのように実装する必要があるという規定はありません。
  • 逆参照された値*a*bは「スワップ可能」である必要があります。これは、それswap(*a, *b)が有効である必要があることを意味します。したがって、逆参照された型は同一である必要がありますが、反復子の型は同一である必要はありません。
  • iter_swapの実装で使用する必要がありstd::reverseます。そのような要件は他のアルゴリズムには課されていないため、これは奇妙に思えます。

seheがSGI docsから見つけたものを借りるには:

厳密に言えばiter_swap冗長です。これは技術的な理由からのみ存在します。状況によっては、一部のコンパイラは を解釈するために必要な型推定を実行するのが困難ですswap(*a, *b)

これらはすべて、それが過去の人工物であることを示唆しているようです。

于 2013-01-24T04:32:21.700 に答える
19

これは、インターネットが多数の相反する情報を生成するシナリオの 1 つと思われます。

の下の標準は、一見すると MSDN の解釈と相関する結果を持つ(および " andは逆参照可能である" こと、および "は " と交換可能である必要がある) こと[C++11: 25.3.3/5]のみを述べています。iter_swap(a,b)swap(*a,*b)ab*a*b

しかし、Microsoft は as-if ルールの考慮を怠っていると思います。これにより、実装が特定のケース (リンクされたリストの要素など)iter_swapよりも高速になるはずです。swap

したがって、私はcomp.std.c++引用が2つの中でより技術的に正確であると信じています.

そうは言っても、実行できる最適化にはかなり厳しい制限があります。たとえば、iter_swap要素の値を物理的に交換するのではなく、単純にノードを再リンクするオーバー リンク リスト要素の実装を考えてみましょう。これは有効な実装ではありませんiter_swap。観察可能な動作が に一致するという要件にswap違反しているからです。

したがって、実際iter_swapには、 を優先する利点はほとんどないことをswapお勧めします。シンプルさと一貫性のために、後者に固執することをお勧めします。いずれにせよ、 C++11 のムーブ セマンティクスはswap、多くの場合に問題を解決するはずです。

于 2013-01-24T04:54:52.653 に答える
12

はい、適切に使用すれば、どちらも同じことを行います。いいえ、std::iter_swap非推奨ではありません (標準の §D互換性機能セクションに配置されることにより)。MSDN の引用は、誤解を招くほど否定的です。std::swap問題は、適切に使用するのが不便なことです。

iter_swapより高い抽象化であるという単純な理由で使用する必要があります。

swap一般に、ユーザー定義型に対してオーバーロードされます。正しい呼び方は

using std::swap;
swap( blah, bleh );

単純ではない

std::swap( blah, bleh );

これは、§17.6.3.2、特に ¶3 に含まれています。

swap(t, u)およびが評価されるコンテキストでは、swap(u, t)「swap」という名前のバイナリ非メンバー関数が、以下を含む候補セットのオーバーロード解決 (13.3) を介して選択されることが保証されます。

— (20.2) でswap定義された 2 つの関数テンプレートと<utility>

— 引数依存ルックアップ (3.4.2) によって生成されるルックアップ セット。

iter_swapは特別なオーバーロードされた名前ではなく、その機能をカスタマイズするには、テンプレートの特殊化を に追加する必要がありnamespace std {}ます。


したがって、iter_swapそうでなければ毎回実装する Swappable インターフェースの一部を便利にカプセル化します。

実装とその特定の引数に意味上の違いがあるかどうかに関係なく、実際にはより使いやすいインターフェイスです。(潜在的な最適化を見逃す必要はありません。MSDN は意見を述べるかもしれませんが、ライブラリの作成者が「下位互換性インターフェイス」を使用して提供するものを予測することはできません。)


iter_swapとは明らかに異なる結果を伴うの特殊化に関してはswap( *a, *b )、それは要件 §25.3.3/5 に準拠していないように思われます。

効果: swap(*a, *b).

*aあなたが引用した例は、とへのポインターが*b操作の前後で両方とも有効であるため、観察可能な違いのように聞こえます。残念ながら、これはライブラリ実装のバグです。

于 2013-01-24T11:40:12.707 に答える
0

どちらを使用する必要がありますか? 何に使うかによります。スワップはオブジェクトに対してのみ機能するため、2 つの独立した整数または文字列または double を交換します。ただし、 iter_swap は、 cplusplus.comで示されているように、2 つの異なるリストの数値を交換できる配列とリストでうまく機能します。

于 2013-01-19T05:25:40.673 に答える