2011-01-24 28 views
13
std::vector<int> v = {1,2,3,4,5}; 
auto i = std::remove(v.begin(),v.end(),3); 
for(auto j = v.begin(); j!= v.end();++j) 
    std::cout << *j; 

uscita effettiva: 12455rimuovere non funziona correttamente

dove viene aggiunto 5 viene?

output desiderato: 1245

Come per ottenere lo stesso?

Io in realtà voglio la dimensione del vettore per cambiare, la risposta data da Prasoon Saurav sembra corretto

risposta

25

remove doesnt actually remove the elements

Rimuovi rimuove dalla gamma [first, last) tutti gli elementi che sono uguali a value. Cioè, rimuovere restituisce un iteratore new_last in modo che l'intervallo [first, new_last) non contenga elementi uguali a value. 1 Gli iteratori nell'intervallo [new_last, last) sono tutti ancora dereferenziabili, ma gli elementi a cui si riferiscono sono non specificato. Rimuovere è stabile, il che significa che l'ordine relativo degli elementi che non sono uguali a valore è unchanged.` algoritmo

std::remove funziona solo utilizzando una coppia di iteratori in avanti e in generale non sa nulla del contenitore sottostante.

È necessario utilizzare il linguaggio erase-remove a realtà rimuovere l'elemento cioè combinare erase con remove

auto i = std::remove(v.begin(),v.end(),3); 
v.erase(i,v.end()); 
for(auto j = v.begin(); j!= v.end();++j) 
    std::cout << *j; 
+4

@Rookie: Guarda quel 'remove()' chiamare di nuovo. Quell'algoritmo vede una sequenza e non ha accesso al contenitore, quindi come potrebbe rimuovere qualcosa da esso? – sbi

+2

"l'idioma di cancellazione-cancellazione" - che è dato proprio alla fine della pagina, nelle "note". –

+2

@GMan: intendevo sviare la risposta ed eliminare il mio commento sopra. Perché hai cancellato la tua risposta? Contiene un punto importante che Prasoon non aveva ancora fatto (ancora). – sbi

2

remove restituisce il nuovo finali . Così la correzione del codice è questo:

std::vector<int> v = {1,2,3,4,5}; 
auto newEnd = std::remove(v.begin(),v.end(),3);//return value stored in newEnd 
for(auto j = v.begin(); j!= newEnd ;++j) //note j!=newEnd 
    std::cout << *j; 

uscita:

1245 

controllare voi stessi: http://www.ideone.com/3AMD9

5

leggere la documentazione relativa std::remove di nuovo.

La funzione non rimuove elementi da un contenitore (non di fatto, non ancora sapere che un contenitore è coinvolta, in quanto vede solo iteratori), si limita muove valori in una sequenza e restituisce una nuova iteratore i in modo tale che tutto l'intervallo [ begin .. i [ contenga tutti gli elementi non rimossi nell'ordine originale. Gli elementi lasciati in [ i .. end [ sono non specificato, ed è vostra responsabilità di eliminare tale intervallo da un contenitore (se ne avete bisogno):

auto i = std::remove(...); 
v.erase(i,v.end()); 

Il motivo per cui si dispone di un ulteriore 5 è che l'algoritmo tipico rimozione copie valori nei fori lasciati dai valori rimossi e poiché i valori oltre l'iteratore i non vengono mai sovrascritti, rimangono gli stessi della sequenza originale.Questo comportamento, tuttavia, non è affidabile: basta eliminare i valori oltre i senza leggerli.

-3

È importante che si stampi la posizione n + 1 del vettore nell'istruzione for(). Dovrebbe essere:

for(auto j = v.begin(); j!= v.end();j++) 
    std::cout << *j; 

j++ senza ++j

+2

Nel contesto di un ciclo 'for', 'j ++' e '++ j' sono equivalenti (anche se, per gli iteratori, potrebbero esserci differenze di prestazioni). –

+0

in questo contesto,' j ++ 'e' ++ j' hanno lo stesso comportamento. – xtofl

Problemi correlati