Peek del prossimo elemento contenitore STL

è possibile sbirciare all’elemento successivo in un contenitore che l’iteratore attuali senza cambiare l’iteratore?

Per esempio in std::set,

int myArray[]= {1,2,3,4};
set <int> mySet(myArray, myArray+4);
set <int>::iterator iter = mySet.begin();

//peek the next element in set without changing iterator.

mySet.erase(iter); //erase the element if next element is n+1
  • Perché non basta fare un copia e anticipo che uno? Assicurati di che controllare se iteratore è pari a .end() prima di continuare!
  • Io credo di aver confuso l’iteratore con un puntatore. quando si assegna un puntatore a puntatore, sia cambierà se un puntatore cambia, ma perché non succede nel caso di un iteratore?
  • Boost ha prior e next funzioni per fare proprio questo (prende l’iteratore per valore, quindi fare una copia come hai suggerito). Vedere boost.org/libs/utility/utility.htm per i dettagli.
  • Se si dispone di due puntatori, e la modifica di uno di essi, l’altro rimane la stessa. Capire, però, che stiamo parlando di cambiare il puntatore il puntatore del referente.
  • Voglio dire, int *i = new int(5); int *j = i; *i = 6; qui j modifiche con i.
  • Si dovrebbe essere attenti a come descrivere le cose. A rigor di termini, quello che hai detto è sbagliato. j non cambia con i, è un’altra variabile che il valore è in alcun modo legata a quella di i. Cosa j punti ai cambiamenti, e così succede i punti lì.
  • Ah ho capito, stiamo cambiando il puntatore o un iteratore dopo la cessione, ma non il valore stesso che esso indica.

InformationsquelleAutor user963241 | 2010-09-09

 

6 Replies
  1. 16

    Non con gli iteratori in generale. Un iteratore non è garantito per essere in grado di operare in modo non distruttivo. L’esempio classico è un Iteratore di Input che, in realtà, rappresenta un sottostante flusso di input.

    C’è qualcosa che funziona per questo tipo di iteratore, però. Un Avanti Iteratore non invalidare precedente copie di se stesso nell’atto di avanzare attraverso la raccolta. Più iteratori (compresi quelli per STL collezioni) sono almeno Avanti Iteratori, se non più funzionali versione – solo Ingresso Iteratori o di Uscita Iteratori sono più limitate. Così si può semplicemente fare una copia del tuo iteratore, incrementare il copia e controllare che, per poi tornare alla originale iteratore.

    Così il peek codice:

    set <int>::iterator dupe = iter;
    ++dupe;
    //(do stuff with dupe)
  2. 25

    C++0x aggiunge una comoda funzione di utilità, std::next, che consente di copiare un iteratore, anticipazioni e restituisce l’avanzata iteratore. Si può facilmente scrivere il proprio std::next attuazione:

    #include <iterator>
    
    template <typename ForwardIt>
    ForwardIt next(ForwardIt it, 
                   typename std::iterator_traits<ForwardIt>::difference_type n = 1)
    {
        std::advance(it, n);
        return it;
    }

    È possibile utilizzare questo come esempio in questo modo:

    if (iter != mySet.end() && next(iter) != mySet.end() && *next(iter) == *iter + 1)
        mySet.erase(iter);
    • +1, non sapevo che era stato adottato. Per inciso, ++ move( iter ) fa la stessa cosa.
    • Io non sono un esperto di modelli, così mi ci è voluto un po ‘ per completamente curarsi di questo piccolo pezzo di codice e quasi andato con la più facile soluzione fornita da @AndrewShephard. Ma all’ultimo minuto si è accorto che questa soluzione è funzionalmente simile (ma non identico) al gcc 4.4.x e 4.9.x il codice sorgente situata a /usr/include/c++/${gcc_version}/bits/stl_iterator_base_funcs.h e così sono andato con questa soluzione invece.
    • Vedo en.cppreference.com/w/cpp/iterator/next dice che è dal c++11, per cui è corretto?
    • C++0x era il titolo di lavoro per C++11 (prima la pianificazione scivolato, quando se sarebbe uscito prima del 2010); C++0x e C++11 realmente significano la stessa cosa.
  3. 0

    Si può sempre fare una copia dell’iteratore e anticipo la copia:

    set <int>::iterator iter = mySet.begin();
    set <int>::iterator iterCopy = iter;
    iterCopy++;
    if (*iterCopy == something)
      mySet.erase(iter);

    Ma attenzione che iterCopy potrebbe non essere più valida una volta che si cancella iter.

    • “iterCopy potrebbe non essere più valida una volta che si cancella iter”. Sarà per un set, ma non per tutti i contenitori STL. Ho google “SGI STL set” o qualsiasi altra cosa, quando ho voglia di un buon riferimento… copre tutto questo.
    • Siate consapevoli, tuttavia, che la SGI è una grande risorsa per il STL. Non è del tutto esatto quanto riguarda la libreria standard del C++ è interessato, tuttavia. Il STL contiene alcuni non-standard contenitori e algoritmi, e i contenitori che sono parte dello standard C++ non match su alcuni dettagli, in particolare per quanto riguarda i contatori.
  4. 0

    per contenitori sequenza (vettore, deque, e l’elenco) si può chiamare, che vi darà una sbirciatina (maggiori informazioni su la parte inferiore di questa link).

  5. 0

    Questo non funzionerà per std::set come la sua natura non consente l’operatore [], ma per i contenitori che fare, si può fare:

    std::vector<int> v;
    v.push_back(3);
    v.push_back(4);
    std::vector<int>::iterator it = v.begin(); 
    std::cout << v[it - v.begin() + 1];

    Ma questo potrebbe essere pericoloso se it punti per l’ultimo elemento del contenitore; ma lo stesso vale per la soluzione di cui sopra. E. g. dovrete effettuare controlli in entrambi i casi.

    • Perché utilizzare operator[] quando si dispone già di un iteratore? Se si desidera che it attuali, utilizzare *it. Se si desidera che l’iteratore dopo it punti, usare qualcosa come *(it + 1) o std::vector<int>::iterator it2(it); std::advance(it2, 1); *it2;.Per inciso, il codice presentato funzionerà solo per un std::vector (non funziona con un std::deque, per esempio).

Lascia un commento