2014-09-19 2 views
6

Sia A un std::vector<double>,aritmetica dei puntatori in testa) iteratore (

È questo ben definito?

if(!A.empty()) 
    std::vector<double>::iterator myBack = A.end() - 1; 

è l'end iteratore solo un bene per uguaglianze e disuguaglianze controlli? Oppure posso eseguire qualche calcolo aritmetico finché rimango nel contenitore?

Sulla mia piattaforma questo codice funziona. Mi chiedo se questo è portatile.

+3

Questo va bene e puoi anche usare 'A.rbegin()'. – perreal

+3

È * iteratore * aritmetico. e dovrebbe essere OK per l'iteratore bidirezionale (come 'std :: vector :: iterator'). – Jarod42

risposta

5

È perfettamente valido come vector::iterator è un iteratore di accesso casuale. È possibile eseguire operazioni aritmetiche su di esso e non dipende dalla piattaforma.

std::vector<double>::iterator it = A.end(); 
while (it != A.begin()){ 
    --it; //this will skip A.end() and loop will break after processing A.front() 
    //do something with 'it' 
} 

Ma A.end() riferisce al teorico elemento past-the-end, quindi non punta ad un elemento e quindi non è dereferenziato. Quindi la migliore pratica è usare iteratore inverso invece di decrementare l'iteratore finale.

Questi due cicli fanno la stessa cosa, il secondo è solo un modo comprensibile e più pulito per farlo.

+0

I due loop non sono identici, il primo non scorre su 'A.front()'. – Jarod42

+1

Ma non penso che 'A.begin() - 1' sia valido. – Jarod42

4

E 'quasi sicuro se si è consapevoli di alcuni casi eccezionali:

A.end() ti dà un iteratore che indica la posizione appena al di là della fine del std::vector. Si dovrebbe non tentare di dereferenziarlo.

Se il vettore ha zero elementi, allora A.end() - 1 è non ben definito. In tutti gli altri casi lo è e puoi effettivamente eseguire l'aritmetica del puntatore finché sei nei limiti del contenitore. Si noti che lo standard garantisce che i dati std::vector sono contigui e impacchettati esattamente nello stesso modo di un array C++ del tipo contiene. L'unica eccezione è std::vector<bool> che si comporta in modo diverso a causa di una specializzazione di imballaggio stretto specificata dagli standard. (Nota bene che sizeof(bool) è non garantito per avere un valore particolare dallo standard).

Se fossi in te, utilizzerei A.rbegin() per accedere all'elemento più a destra e controllare il valore restituito prima di procedere e attenermi alla formulazione dell'iteratore. È fin troppo facile dimenticare la specializzazione std::vector<bool>.

+0

Non sono sicuro del caso 'bool'. Non è questo iteratore - non puntatore - aritmetica, come sottolineato da @ Jarod42? Non dovrebbe questo renderlo completamente sicuro e ben definito anche per 'std :: vector '? –

+0

Se un 'std :: vector ' ha esattamente 3 elementi allora non sono convinto che 'A.end() - 1' sia definito se' sizeof (bool) == sizeof (int) '. Potrei sbagliarmi comunque. Ma se lanci qualcosa per "bool *", allora sei sicuramente nei guai. Forse un operatore sovraccarico sull'iteratore inverso 'bool' si occupa di questo. Risposta breve: non lo so. Sto pensando di mettere una taglia su questa domanda. – Bathsheba

+0

Se 'std :: vector :: iterator' ha funzionato come dici tu, la semplice iterazione sul vettore non funzionerebbe. Finché si opera su iteratori, '- 1' deve spostarlo di un elemento logico, non di' sizeof (bool) 'byte.Metto un po 'di codice su http://ideone.com/2pAiE1, e funziona come mi aspetto finché il risultato della sottrazione è all'interno del contenitore. Dovresti compilarlo con '_GLIBCXX_DEBUG' (o equivalente per il tuo compilatore) per farlo abbaiare quando superi i limiti. –