C ++ STLベクトル:インデックスからイテレーターを取得しますか?


200

そのため、stlベクトルの要素にindex []でアクセスする一連のコードを記述しましたが、今度は、ベクトルのチャンクのみをコピーする必要があります。それはvector.insert(pos, first, last)私が欲しい関数のように見えます... intとして最初と最後しか持っていないことを除いて。これらの値のイテレータを取得できる良い方法はありますか?


1
次も参照してください:stackoverflow.com/q/2152986/365102
Mateen Ulhaq

私が間違っていない場合は、いずれの回答も境界チェックを行わないため、問題になる可能性があります。具体的には、std :: advance docsは、基礎となるコンテナーの境界を越えるためにそれを使用する場合の動作は未定義であると述べています。
Martin Pecka

回答:


293

これを試して:

vector<Type>::iterator nth = v.begin() + index;

4
一般的に、STLイテレーターではポインターと同じ演算を使用できます。これらは、STLアルゴリズムを使用するときに交換できるように設計されています。
ビンセントロバート

18
@VincentRobert:他の方法です。ポインタは、STLランダムイテレータの有効な実装であり、最も強力なカテゴリです。ただし、順方向反復子などのその他のそれほど強力ではないカテゴリーは、同じ演算をサポートしていません。
MSalters 2013年

6
私はこの答えに私の5セントを追加してお勧めしたいと思いますstd::next(v.begin(), index)
stryku

87

@dirkgentlyで述べた方法( v.begin() + index )ベクトルのための速い素晴らしく、

しかし、最も一般的な方法であり、ランダムアクセスの場合、イテレータは一定の時間でも機能します。 std::advance( v.begin(), index )


使用法の違いを編集

std::vector<>::iterator it = ( v.begin() + index );

または

std::vector<>::iterator it = v.begin();
std::advance( it, index );

@litbノートの後に追加。


std :: advanceは最初の引数として非constイテレータを必要としませんか?
goldPseudo 2009年

std :: advanceをconstおよびnon-constイテレータで使用できます
bayda

1
その点でmsvcを信頼すべきではありません。この種のものを受け入れるようにする非標準の拡張機能がありますが、他のすべてのコンパイラは標準で動作し、それを拒否します。
Johannes Schaub-litb

1
問題は「const」の意味の混乱だと思います。advance()は、T型のconst要素を参照する可変反復子であるconst_iterator <T>で問題なく機能します。それ自体がconstであるイテレーターオブジェクト(つまり、「const iterator <T>」または「iterator <T> const」)では機能しません。
j_random_hacker

7
を処理しいることがわかっている場合はstd::vector、を使用しても意味がありませんstd::advance。コンテナにとらわれないコードを書いていると思わせるだけです(あなたはそうではなく、イテレータの無効化ルール、さまざまな実行時の複雑さなどを考えています)。std::advance意味のある唯一のケースは、どのイテレータを扱っているのかわからないテンプレートを自分で書く場合です。
Frerich Raabe 2013

47

また; auto it = std::next(v.begin(), index);

更新:C ++ 11x準拠のコンパイラが必要


2
これはC ++ 11の方法であることに注意してください!std :: nextはstd :: advanceと同等です。算術を使用するのではなくこれらの関数を使用すると、コンテナータイプの交換がはるかに簡単になります。std :: beginとstd :: endのように、c-arrays afaikでも機能します。
Zoomulator、2012年

2
std :: advanceは、参照として出力を使用し、戻り値を使用しないため、ばかによって設計されていることにも注意してください。
Viktor Sehr

1
for(auto it = begin(c); it!= end(c); advance(it、n)){...}
Zoomulator

2
どちらにも用途があります。stda :: advanceは、イテレータを変更するのに役立ちます。これはループでのパフォーマンスの問題です。あなたが示唆するように、私は割り当ての場合には次のほうを好みます。私はそれをばかげていると主張することは少し厳しいと思いました。どちらの機能も基本的には同じですが、異なる状況を想定して設計されています。
Zoomulator、2013年

5
@Zoomulator:イテレータのコピーがパフォーマンスの問題である場合、対処する必要のある大きな問題があります。
Mooing Duck 2014

8

またはあなたが使うことができます std::advance

vector<int>::iterator i = L.begin();
advance(i, 2);

-3

実際にはstd :: vectorは、必要に応じてCタブとして使用するためのものです。(私が知る限り、C ++標準では、ベクトルの実装を要求しています- ウィキペディアの配列の置き換え)たとえば、次のようにすることは完全に合法です。

int main()
{

void foo(const char *);

sdt::vector<char> vec;
vec.push_back('h');
vec.push_back('e');
vec.push_back('l');
vec.push_back('l');
vec.push_back('o');
vec.push_back('/0');

foo(&vec[0]);
}

もちろん、fooはパラメーターとして渡されたアドレスをコピーしてどこかに保存してはなりません。あるいは、プログラムでvecに新しい項目をプッシュしたり、容量の変更を要求したりしないようにする必要があります。またはリスクセグメンテーションエラー...

したがって、あなたの例ではそれは

vector.insert(pos, &vec[first_index], &vec[last_index]);

それらが単なるポインタである場合、なぜイテレータに抽象化することにしたのか不思議に思われます...それらは本質的にこれらの機能を「隠している」のです。
mpen 2009年

一貫性のために?コード内の他の種類のコンテナーのベクターインスタンスを簡単に削除できるためです。
yves Baumes 2009年

4
&vec [i]は、vector <> :: iteratorと必ずしも互換性のないポインターを生成します。vec.begin()+ iには、ライブラリで定義されているイテレータ(デバッグモードのチェック済みイテレータなど)であるという利点があります。したがって、ポインタ(I / Oなど)が必要ない場合は、常にイテレータを優先する必要があります。
selibitze 2009

@KerrekSB c ++標準ドラフトの23.3.6.1から:「ベクトルの要素は連続して格納されます。つまり、vがvector <T、Allocator>である場合、Tがbool以外の型である場合、ID&v [に従います。 n] ==&v [0] + n for all 0 <= n <v.size() "
yves Baumes

2
@yvesBaumes:それはベクトル反復子とは何の関係もありません。しかし、裸のポインタがあることは事実です彼らだけじゃない-また、イテレータのベクターイテレータ。
Kerrek SB 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.