web-dev-qa-db-ja.com

イテレータを2増やす方法は?

誰でもイテレータを2増やす方法を教えてもらえますか?

iter++は利用可能です-する必要がありますかiter+2?どうすればこれを達成できますか?

62
Cute

std::advance( iter, 2 );

このメソッドは、ランダムアクセスイテレーターではないイテレーターで機能しますが、実装によって特殊化して、iter += 2ランダムアクセスイテレータで使用する場合。

94
CB Bailey

http://www.cplusplus.com/reference/std/iterator/advance/

std::advance(it,n);

ここで、nは2です。

この関数の美しさは、「it」がランダムアクセス反復子である場合、高速

it += n

操作が使用されます(つまり、vector <,> :: iterator)。それ以外の場合は

for(int i = 0; i < n; i++)
    ++it;

(つまり、list <..> :: iterator)

26
Maik Beckmann

イテレータの変更可能な左辺値がない場合、または特定のイテレータのコピーを取得する(元のイテレータを変更せずに残す)場合は、C++ 11に新しいヘルパー関数が付属します- std::next / std::prev

std::next(iter, 2);          // returns a copy of iter incremented by 2
std::next(std::begin(v), 2); // returns a copy of begin(v) incremented by 2
std::prev(iter, 2);          // returns a copy of iter decremented by 2
17
Piotr Skotnicki

「追加による割り当て」演算子を使用できます

iter += 2;
7
teabot

コンテナに次の要素が十分にあるかどうかわからない場合は、増分するたびにコンテナの終わりを確認する必要があります。 ++もstd :: advanceもあなたのためにそれを行いません。

if( ++iter == collection.end())
  ... // stop

if( ++iter == collection.end())
  ... // stop

独自のバウンドセキュアアドバンス機能を使用することもできます。

終わりを超えないことが確実な場合は、std :: advance(iter、2)が最適なソリューションです。

4
Jem

std :: advancestd :: next の両方を使用できますが、両者には違いがあります。

advanceは引数を変更し、何も返しません。したがって、次のように使用できます。

vector<int> v;
v.Push_back(1);
v.Push_back(2);
auto itr = v.begin();
advance(itr, 1);          //modifies the itr
cout << *itr<<endl        //prints 2

nextは、イテレータの変更されたコピーを返します。

vector<int> v;
v.Push_back(1);
v.Push_back(2);
cout << *next(v.begin(), 1) << endl;    //prints 2
3
skpro19

リストのサイズがステップの偶数倍ではない場合、オーバーフローを防ぐ必要があります。

static constexpr auto step = 2;

// Guard against invalid initial iterator.
if (!list.empty())
{
    for (auto it = list.begin(); /*nothing here*/; std::advance(it, step))
    {
        // do stuff...

        // Guard against advance past end of iterator.
        if (std::distance(it, list.end()) > step)
            break;
    }
}

コレクションの実装によっては、距離の計算が非常に遅くなる場合があります。以下が最適で読みやすいです。クロージャーは、const参照によって渡されるリストの終了値を持つユーティリティテンプレートに変更できます。

const auto advance = [&](list_type::iterator& it, size_t step)
{
    for (size_t i = 0; it != list.end() && i < step; std::next(it), ++i);
};

static constexpr auto step = 2;

for (auto it = list.begin(); it != list.end(); advance(it, step))
{
    // do stuff...
}

ループがない場合:

static constexpr auto step = 2;
auto it = list.begin();

if (step <= list.size())
{
    std::advance(it, step);
}
0
evoskuil