ベクトルを反復処理しているので、反復子が現在指しているインデックスが必要です。これは2つの方法で実行できます。
it - vec.begin()
std::distance(vec.begin(), it)
これらの方法の長所と短所は何ですか?
Naveenとは反対の理由で、it - vec.begin()
を正確に使用することをお勧めします。したがって、ベクトルをリストに変更した場合、はコンパイルされません。すべての繰り返しでこれを実行すると、O(n)アルゴリズムをO(n ^ 2)アルゴリズムに簡単に変換できます。
もう1つの選択肢は、反復中にコンテナ内でジャンプしない場合は、インデックスを2番目のループカウンタとして保持することです。
注:it
は、コンテナー・イテレーターの一般名、std::container_type::iterator it;
です。
コードを変更しなくてもコンテナを変更できるようになるので、std::distance(vec.begin(), it)
をお勧めします。たとえば、ランダムアクセスイテレータを提供していないstd::list
の代わりにstd::vector
を使用することにした場合、コードはコンパイルされます。 std :: distanceはイテレータの特性に応じて最適な方法を選択するので、パフォーマンスの低下もありません。
UncleBensとNaveenが示しているように、両方に良い理由があります。どちらが「より良い」かは、どのような振る舞いがしたいかによって異なります。一定時間の振る舞いを保証したいのか、それとも必要に応じて線形時間にフォールバックしたいのか
it - vec.begin()
は一定の時間がかかりますが、operator -
はランダムアクセスイテレータでしか定義されていないので、例えばコードはリストイテレータではまったくコンパイルされません。
std::distance(vec.begin(), it)
はすべてのイテレータ型で機能しますが、ランダムアクセスイテレータで使用された場合にのみ定時操作になります。
どちらも「より良い」というわけではありません。あなたが必要とすることをするものを使いなさい。
私はこれが好きです:it - vec.begin()
、私にとってそれは明らかに「最初からの距離」を言っているので。イテレータでは、算術の観点から考えることに慣れているので、ここでは-
記号が最も明確な指標です。
あなたのアルゴリズムが既に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()
はソースコードが短い - タイピング作業が少なく、スペースが消費されません。あなたの質問に対する正しい答えが好みの問題であることが明らかになっているので、これはもも有効な議論である可能性があります。