2011-09-08 13 views
6

Ho una domanda sulle prestazioni dello std :: vector <> in C++. È più veloce riutilizzare lo stesso vettore chiamando il suo metodo clear() o è più veloce ricreare il vettore?cos'è più veloce: ricrea o clear()?

L'esempio che segue un codice di vita reale, è solo per fare chiaro quale sia la domanda è:

//Example ONE: is this faster 
std::vector<int> foo; 
for(int i = 0; i < 100; ++i) 
{ 
    foo.clear(); 
    for(int j = 0; j < 100; ++j) 
    { 
     foo.push_back(i+j); 
    } 
} 

//Example TWO: or is that faster? 
for(int i = 0; i < 100; ++i) 
{ 
    std::vector<int> foo; 
    for(int j = 0; j < 100; ++j) 
    { 
     foo.push_back(i+j); 
    } 
} 
+0

Le cose non dipendono dall'implementazione? –

+6

Profile it. Boooooring! –

+3

Perché tutti i downvotes? – Daniel

risposta

7

Il clear() non può dal suo contratto di deallocare la memoria vector, invece solo imposta il flag interno "dimensione" a 0, in modo che il metodo sia più veloce.

+1

Più che "leggermente", direi. –

+1

Non conosco alcuna implementazione che rilasci la memoria. –

+0

@David: creazione di un nuovo vettore! : D [modifica: sì, ok, lasciando morire quello vecchio] –

0

L'esempio 2 ha ripetuto l'allocazione dell'heap per l'array all'interno di std :: vector. L'Esempio 1 è più veloce perché evita di allocare ripetutamente memoria nell'heap a meno che il vettore non debba essere ridimensionato internamente.

+0

's/allocare memoria sull'heap/allocare dinamicamente memoria /' –

0

Dovrai eseguire benchmark per il tuo compilatore. I metodi clear() e "allocate" dipendono dall'implementazione.

+0

Che la capacità di un vettore non si riduca mai non dipenda affatto dall'implementazione. [edit: sebbene C++ 11 _does_ abbia 'shrink_to_fit'] –

+0

@Tomalak: In realtà stavo pensando a questo. Non esiste una clausola specifica nello standard che inibisca l'implementazione dal liberare effettivamente la memoria. Un vettore che * si restringe * sarebbe più difficile da implementare in molti casi (mantenendo il * costo costante * ammortizzato * di 'push_back'), ma non penso che sarebbe * impossibile *, e che per il caso generale di 'cancella', con le specifiche di' clear() 'Non vedo alcun motivo per cui un'implementazione conforme non può rilasciare la memoria (quindi, ancora una volta, non ho approfondito lo standard cercando questo caso particolare ...) –

+0

@ David: Anch'io ci sto passando sopra. Non vedo alcuna garanzia che 'clear' * debba * richiamare' reserve'. Mi sembra abbastanza fortemente implicito, ma non è dichiarato. –

2

Dipende dall'implementazione di std::vector nella libreria standard C++ che si sta utilizzando, ma è probabile che il primo caso sia più veloce perché la maggior parte delle implementazioni non rilasciano effettivamente memoria allocata quando si chiama std::vector::clear. Quindi il primo non esegue allocazioni ripetute una volta che il ciclo interno è stato eseguito la prima volta.

0

Per entrambi cancellare un vettore e ridurre la sua capacità di minima per la realizzazione, Scott Meyers raccomanda il trucco di swap:

std::vector<int>().swap(foo); 

Sarebbe anche più veloce rispetto scorrendo il vettore con un ciclo arrotolato a mano a ripristina il suo contenuto.

1

Sì. No. Il primo è più veloce, probabilmente. Dipende. L'unica risposta utile viene dal profiling del tuo codice nel tuo ambiente.

Prova a profilare il codice per vedere cosa succede. Compilare your program at ideone rivela che, per un particolare compilatore/os/machine/run, il tuo primo esempio è 4x più veloce.

E this program mostra una soluzione intermedia, che va più veloce di # 2, più lento di # 1, per questo particolare compilatore/OS/macchina/run.

0

In questo caso specifico, il caso di riutilizzo sarà probabilmente più veloce sulla maggior parte delle macchine. Stai memorizzando dati primitivi che non hanno bisogno di distruzione (o che hanno anche un distruttore). D'altra parte, se il vettore contiene oggetti non POD, ogni elemento verrà distrutto dalla chiamata a clear. Nella terza mano, tutti i dati accumulati dovranno essere infine distrutti.