回答:
私はit - vec.begin()
ナビーンによって与えられた反対の理由で正確に好みます:それでそれはしません、ベクターをリストに変更してコンパイルされ。すべての反復でこれを行うと、O(n)アルゴリズムをO(n ^ 2)アルゴリズムに簡単に変換してしまう可能性があります。
反復中にコンテナー内をジャンプしない場合の別のオプションは、インデックスを2番目のループカウンターとして保持することです。
注:it
はコンテナイテレータの一般的な名前ですstd::container_type::iterator it;
。
it
ですか?
std::container_type::iterator it;
std::list
は、位置による要素への直接アクセスを提供しないため、実行できない場合はlist[5]
、実行できないはずですlist.begin() + 5
。
std::distance(vec.begin(), it)
コードを変更せずにコンテナを変更できるので、私は好みます。たとえば、ランダムアクセスイテレータを提供しないstd::list
代わりに使用する場合std::vector
でも、コードはコンパイルされます。std :: distanceはイテレーターの特性に応じて最適な方法を選択するため、パフォーマンスも低下しません。
vec
は悪いニュースです。コンテナータイプをテンプレートパラメーターとして使用して、コードがジェネリックに書き換えられた場合、それは、ランダムアクセス以外の反復子の処理について話すことができる(そしてすべきである)ときです;-)
vec
もかなり悪いニュースです。
UncleBensとNaveenが示したように、両方の理由があります。どちらが「より良い」かは、希望する動作に依存します。一定時間の動作を保証しますか、それとも必要に応じて線形時間にフォールバックしますか?
it - vec.begin()
は一定の時間がかかりoperator -
ますが、これはランダムアクセス反復子でのみ定義されるため、たとえば、コードはリスト反復子でコンパイルできません。
std::distance(vec.begin(), it)
すべてのイテレータタイプで機能しますが、ランダムアクセスイテレータで使用した場合のみ、一定時間の操作になります。
どちらも「良い」ものではありません。必要なことを行うものを使用してください。
私はこれが好きですit - vec.begin()
。なぜなら、私には「最初からの距離」がはっきりと書かれているからです。イテレータを使うと、私たちは算術の考え方に慣れているので、ここでの-
符号は最も明確な指標です。
distance
です。
it++
、のようなものstd::increment(it)
ではありませんか?それも不明確なものとしてカウントされませんか?
++
オペレータは、我々はイテレータをインクリメントする方法としてSTLシーケンスの一部として定義されます。 std::distance
最初の要素と最後の要素の間の要素数を計算します。-
オペレーターが働いているという事実は単なる偶然です。
アルゴリズムを既に制限/ハードコーディングしている場合は、アルゴリズムを使用しstd::vector::iterator
てstd::vector::iterator
だけ、本当にあなたが使用して終了れる方法は重要ではありません。アルゴリズムは、もう一方を選択することで違いが出る可能性がある点を超えてすでに具体化されています。どちらもまったく同じことを行います。それは個人的な好みの問題です。個人的には明示的な減算を使用します。
一方、アルゴリズムの一般性をより高く維持したい場合、つまり、将来的には他のイテレータタイプに適用される可能性を許容する場合、最適な方法は意図に依存します。 。これは、ここで使用できるイテレータタイプに関してどの程度制限したいかに依存します。
明示的な減算を使用する場合、アルゴリズムはかなり狭いクラスのイテレータ、つまりランダムアクセスイテレータに制限されます。(これはあなたが今得たものですstd::vector
)
を使用するdistance
場合、アルゴリズムははるかに広いクラスのイテレータ、つまり入力イテレータをサポートします。
もちろん、distance
非ランダムアクセス反復子の計算は、一般に非効率的な操作です(ランダムアクセスの場合は、減算と同じくらい効率的です)。アルゴリズムが非ランダムアクセス反復子に対して効率的に意味を成すかどうかを決めるのはあなた次第です。結果として生じる効率の損失がアルゴリズムを完全に役に立たないものにするという点で壊滅的である場合、減算に固執する必要があります。したがって、非効率的な使用を禁止し、ユーザーに他の反復子タイプの代替ソリューションを探すことを強います。非ランダムアクセス反復子を使用した効率がまだ使用可能な範囲内にある場合はdistance
、アルゴリズムがランダムアクセス反復子でより適切に機能するという事実を使用して文書化する必要があります。
http://www.cplusplus.com/reference/std/iterator/distance/によると、vec.begin()
はランダムアクセスイテレータであるため、distanceメソッドは-
演算子をます。
したがって、答えは、パフォーマンスの観点からは同じですがdistance()
、誰かがコードを読んで理解する必要がある場合は、使用する方が理解しやすいでしょう。
私は-
バリアントstd::vector
のみを使用します-意味がかなり明確であり、操作の単純さ(これはポインタの減算にすぎません)は構文で表現されます(distance
反対側では、ピタゴラスのように聞こえます)最初に読んでいませんか?)UncleBenが指摘するように、誤って次のように変更さ-
れた場合の静的アサーションとしても機能しますvector
list
ます。
また、私はそれがはるかに一般的だと思います-しかし、それを証明する数字はありません。マスター引数:it - vec.begin()
ソースコードが短い-入力作業が減り、消費されるスペースが減ります。あなたの質問に対する正しい答えが好みの問題であると結論づけられることは明らかであるので、これは有効な議論になることもあります。
以下は、インデックスとともに10の「すべて」の出現を検索する例です。これはいくつかの助けになると思いました。
void _find_all_test()
{
vector<int> ints;
int val;
while(cin >> val) ints.push_back(val);
vector<int>::iterator it;
it = ints.begin();
int count = ints.size();
do
{
it = find(it,ints.end(), 10);//assuming 10 as search element
cout << *it << " found at index " << count -(ints.end() - it) << endl;
}while(++it != ints.end());
}