wake-up-neo.net

Wie kann man einen Iterator um 2 erhöhen?

Kann mir jemand sagen, wie ich den Iterator um 2 erhöhen kann?

iter++ ist verfügbar - muss ich iter+2 tun? Wie kann ich das erreichen?

57
Cute

std::advance( iter, 2 );

Diese Methode funktioniert für Iteratoren, bei denen es sich nicht um Iteratoren mit wahlfreiem Zugriff handelt, sie kann jedoch durch die Implementierung so spezialisiert werden, dass sie bei Verwendung mit Iteratoren mit wahlfreiem Zugriff nicht weniger effizient ist als iter += 2.

86
CB Bailey

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

std::advance(it,n);

wobei n in Ihrem Fall 2 ist.

Das Schöne an dieser Funktion ist, dass, wenn "es" ein Iterator mit wahlfreiem Zugriff ist, der schnelle

it += n

operation wird verwendet (d. h. Vektor <,> :: Iterator). Ansonsten wird es gerendert

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

(d. h. Liste <..> :: Iterator)

23
Maik Beckmann

Wenn Sie keinen veränderbaren Wert eines Iterators haben oder eine Kopie eines Iterators erhalten möchten (wobei der ursprüngliche Iterator unverändert bleibt), enthält C++ 11 neue Hilfsfunktionen - 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
13
Piotr Skotnicki

Sie können den Operator 'Zuweisung durch Addition' verwenden

iter += 2;
7
teabot

Wenn Sie nicht wissen, ob Sie als nächstes genügend Elemente in Ihrem Container haben oder nicht, müssen Sie das Ende Ihres Containers zwischen den einzelnen Schritten überprüfen. Weder ++ noch std :: advance erledigen das für Sie.

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

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

Sie können sogar Ihre eigene gebundene sichere Vorlauffunktion ausführen.

Wenn Sie sicher sind, dass Sie nicht am Ende vorbeikommen, ist std :: advance (iter, 2) die beste Lösung.

4
Jem

Wir können sowohl vor als auch als nächstes verwenden. Aber es gibt einen Unterschied zwischen den beiden. "advance" ändert sein Argument und gibt nichts zurück. So kann es verwendet werden als: 

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" gibt eine modifizierte Kopie des Iterators zurück

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

Angenommen, die Listengröße ist möglicherweise nicht ein Vielfaches von Schritten, die Sie vor Überlauf schützen müssen:

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;
    }
}

Abhängig von der Erfassungsimplementierung kann die Abstandsberechnung sehr langsam sein. Unten ist optimal und lesbarer. Die Schließung könnte in eine Utility-Vorlage geändert werden, wobei der Listenendwert von const als Referenz übergeben wird:

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...
}

Wenn es keine Schleife gibt:

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

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