2010-08-19 14 views

risposta

37

rimuovi [...] mette gli elementi 'rimossi' all'inizio della sequenza

Cosa? No. Entrambi remove_if e partition mettono gli elementi "buoni" per primi. partition inserisce gli elementi "cattivi" dopo di ciò, mentre remove_if non specifica ciò che viene dopo - potrebbe essere gli elementi non validi, ma potrebbe anche essere copie di qualsiasi elemento (buono o cattivo).

Ad esempio, se si partition 1 2 3 4 5 su anche, si potrebbe ottenere 2 4 5 3 1 (si noti che ogni elemento si verifica esattamente una volta), mentre se si remove_if i dispari elementi, si potrebbe prendi 2 4 3 4 5 (annota i duplicati).

+0

grazie, l'ho capito –

2

From The C++ Standard Library: Un tutorial e una Riferimento

remove() - Rimuove gli elementi con un dato valore, logicamente solo per loro sovrascrivendo con i seguenti elementi che non sono stati rimossi. Non modificare il numero di elementi negli intervalli su cui operano. Al contrario, essi restituiscono la posizione del nuovo "fine" della gamma

partizione() - Cambia l'ordine degli elementi in modo che gli elementi che corrispondono a un criterio sono nella parte anteriore

stable_partition() - Uguale partizione(), ma conserva l'ordine relativo degli elementi corrispondenti e non corrispondenti

+0

spiegazione piacevole. – Chubsdad

-1

partizione - "gruppi" gli elementi di un contenitore secondo una certa predicato (es pari e dispari in uno std :: vector)

remove - rimuove un certificato un valore in un contenitore; infatti elementi vengono spostati alla fine del primo contenitore, un iteratore alla nuova estremità è restituito e gli elementi "cancellata" sono ancora accessibili

EDIT:

remove - rimuove un certo valore da un contenitore; elementi non sono spostati alla fine del primo contenitore come detto sopra, un iteratore alla nuova estremità viene restituito ma iteratori nell'intervallo [newEnd, ultimo) sono ancora dereferenceable quindi accessibile ma gli elementi che indicano è specificato.

+0

Questo è sbagliato, rimuovere sovrascrive gli elementi 'rimossi' dai seguenti, quindi non tutti potrebbero essere accessibili successivamente ... – MartinStettner

+0

Vorrei sapere cosa c'è di sbagliato nella mia risposta se possibile. Forse imparerò qualcosa nel processo. – celavek

+0

@MartinStettner Penso che tu abbia torto. Dalla documentazione "Rimuovi rimuove dall'intervallo [primo, ultimo] tutti gli elementi uguali al valore, ovvero rimuove un iteratore new_last in modo tale che l'intervallo [first, new_last) non contenga elementi uguali al valore. [1] Gli iteratori nell'intervallo [new_last, last) sono tutti ancora dereferenziabili, ma gli elementi a cui puntano non sono specificati. Remove è stabile, il che significa che l'ordine relativo di elementi che non sono uguali al valore è invariato. " http://www.sgi.com/tech/stl/remove.html – celavek

12

remove_if non mettere gli elementi rimossi da nessuna parte; gli elementi dopo la nuova fine avranno i loro vecchi valori, quindi alcuni degli elementi rimossi potrebbero mancare e alcuni degli elementi conservati potrebbero essere duplicati. Questo è più veloce di partition, e può essere fatto con iteratori forward, mentre partition richiede iteratori bidirezionali.

Aggiornamento: in C++ 0x, partition sarà solo richiede avanti iteratori, ma sarà ancora più lento se gli iteratori non sono bidirezionali.

+0

Se 'partition' richiede iteratori bidirezionali, come mai funziona su un' forward_list'? – fredoverflow

+0

@FredOverflow: poiché C++ 0x modifica il contratto di 'partition' per portare avanti gli iteratori. –

+1

'partition' è molto più veloce di' remove_if' in alcuni casi. Se l'elemento da rimuovere è all'inizio di un vettore enorme, 'remove_if' sposta l'intera cosa a sinistra mentre' partition' semplicemente scambierà l'elemento da rimuovere con l'ultimo. – aberaud

4

Se ho capito bene, remove non scambia alcun elemento, ma semplicemente sposta elementi per i quali il predicato (nel caso di remove_if) è falso all'inizio della sequenza. Se si dispone di

a = [1,1,1,2,3]

e chiamare remove(a.begin(),a.end(),1), avrete

a = [2,3,1,2,3]

dopo. remove restituisce un iteratore al terzo elemento in questo caso (se non ricordo male ...

partition d'altra parte conserva tutti gli elementi originali della sequenza ma modifica il loro ordine in modo tale che gli elementi per i quali il predicato indicato è vero siano posti di fronte a elementi per i quali non lo è.

partition(a.begin(), a.end(), not_equal<int>(1)) cede

a = [2,3,1,1,1]

+2

Nota che non è garantito cosa 'std :: remove()' lascia dietro _after_ il nuovo iteratore di fine restituisce. Mentre il risultato che mostri è probabile, non è garantito. – sbi

+0

Ho pensato che 'std :: remove' avrebbe lasciato invariati gli elementi dietro il nuovo iteratore finale (anch'essi sarebbero rimasti accessibili). Ma potrei essere smentito dallo standard :) ... – MartinStettner

+0

Lo standard non specifica cosa succede agli elementi dopo la fine del nuovo intervallo. Mentre è difficile immaginare che qualsiasi implementazione ragionevole li possa toccare, non c'è alcuna garanzia. –

Problemi correlati