2013-03-08 18 views
8

So che l'allocazione dinamica della memoria manuale è una cattiva idea in generale, ma a volte è una soluzione migliore rispetto all'uso, ad esempio, std::vector?Overhead to using std :: vector?

Per dare un esempio grezzo, se dovessi memorizzare un array di numeri interi n, dove n < = 16, ad esempio. Ho potuto renderlo operativo

int* data = new int[n]; //assuming n is set beforehand 

oppure utilizzando un vettore:

std::vector<int> data; 

È assolutamente sempre una migliore idea di utilizzare un std::vector o potrebbe esserci situazioni pratiche dove ripartizione manualmente la memoria dinamica sarebbe un migliore idea, per aumentare l'efficienza?

+0

Non è necessario 'push_back' . 'std :: vector (n)' è * quasi * equivalente alla tua versione di array dinamico, tranne per il fatto che gli interi 'n' sono valore, quindi zero, inizializzati nel vettore. – juanchopanza

+0

@juanchopanza: punto giusto. Ho rimosso la parte 'push_back'. Non doveva essere parte del confronto. –

risposta

11

E 'sempre meglio usare std::vector/std::array, almeno fino a quando si può dimostrare in modo conclusivo (mediante profilatura) che la soluzione T* a = new T[100]; è notevolmente più veloce nella vostra situazione specifica. È improbabile che ciò accada: vector/array è uno strato estremamente sottile attorno a un semplice vecchio array. C'è un sovraccarico ai limiti di controllo con vector::at, ma è possibile aggirare il problema utilizzando operator[].

+3

Il solito motivo per utilizzare gli array in stile C non ha nulla a che fare con la velocità; è per l'inizializzazione statica e per il compilatore per determinare la dimensione in base al numero di inizializzatori.(Che, ovviamente, non si applica mai agli array allocati dinamicamente). –

+0

@James Se sto leggendo il tuo commento correttamente, ti opponi al fatto che io sembro essere bashing sugli array in stile C senza dire che intendo quelli assegnati dinamicamente? Se è così, ho modificato la mia risposta a riguardo. (Inoltre, +1 alla risposta.) – us2012

+1

Questo lo risolve. Non sapevo che 'vector' /' array' fosse un sottile strato. Ho pensato che con tutte le funzionalità, deve avere un overhead significativo. –

4

Se si conoscono le dimensioni in anticipo (soprattutto al momento della compilazione) e non è necessario il ridimensionamento dinamico delle capacità di std::vector, allora l'uso di qualcosa di più semplice va bene.

Tuttavia, qualcosa dovrebbe preferibilmente essere std::array se si dispone di C++ 11, o qualcosa come boost::scoped_array in caso contrario.

Dubito che ci sarà molto guadagno di efficienza a meno che non riduca significativamente le dimensioni del codice o qualcosa del genere, ma è più espressivo che vale comunque la pena.

4

Si dovrebbe cercare di evitare C -stile-array in C++ quando possibile. Il STL fornisce contenitori che di solito sono sufficienti per ogni esigenza. Immagina semplicemente la riallocazione di un array o l'eliminazione di elementi fuori dal suo centro. Il contenitore ti protegge dal maneggiarlo, mentre dovresti prenderti cura di te stesso, e se non lo hai fatto cento volte è abbastanza incline agli errori.
Un'eccezione è, naturalmente, se si affrontano problemi di basso livello che potrebbero non essere in grado di gestire i container STL.

Ci sono già state alcune discussioni su questo argomento. Vedi here su SO.

+0

+1 per il collegamento alla fine, che dovrebbe distruggere una volta per tutte il mito che l'accesso agli elementi vettoriali sia in qualche modo lento. – us2012

+0

+1 per il collegamento. Avrei dovuto scoprirlo prima, in realtà ... –

0

In n è noto al momento della compilazione, allora si dovrebbe scegliere std::array come:

std::array<int, n> data; //n is compile-time constant 

e se n non è noto al momento della compilazione, o la matrice potrebbe crescere in fase di esecuzione, poi per std::vector :

std::vector<int> data(n); //n may be known at runtime 

o in alcuni casi, si può anche preferire std::deque che è più veloce std::vector in qualche scenario.Vedere questi:

Speranza che aiuta.

+0

A meno che tu non sappia che 'n' è molto, molto piccolo, probabilmente non dovresti dichiarare le variabili locali come' std :: array'. A meno che non ci sia una ragione molto specifica per fare altrimenti, userei semplicemente 'std :: vector' --- se conosco la dimensione, inizializzerò il vettore con la dimensione corretta. (Ciò suppone anche che il tipo abbia un costruttore predefinito). –

3

È sempre sempre una buona idea usare un file std :: vector o ci potrebbero essere situazioni pratiche in cui allocare manualmente la memoria dinamica sarebbe un'idea migliore, per aumentare l'efficienza?

Chiamami un semplice, ma 99.9999 ...% delle volte vorrei utilizzare solo un contenitore standard. La scelta predefinita dovrebbe essere std::vector, ma anche std::deque<> could be a reasonable option sometimes. Se la dimensione è nota al momento della compilazione, optare per std::array<>, che è un wrapper leggero e sicuro di array in stile C che introduce zero overhead.

I contenitori standard espongono le funzioni membro per specificare la quantità di memoria riservata iniziale, pertanto non si avranno problemi con le riallocazioni e non sarà necessario ricordare l'array delete[]. Onestamente non vedo perché si dovrebbe usare la gestione manuale della memoria.

L'efficienza non dovrebbe essere un problema, dal momento che si dispone di funzioni membro di lancio e non di lancio per accedere agli elementi contenuti, in modo da avere una scelta se favorire la sicurezza o le prestazioni.

2

std :: vector potrebbe essere costruito con un parametro size_type che istanziare il vettore con il numero specificato di elementi e che fa un singolo allocazione dinamica (stesso del vostro array) e inoltre è possibile utilizzare riserva a diminuire il numero di riassegnazioni rispetto al tempo di utilizzo.

8

Non riesco a pensare a nessun caso in cui abbia senso allocare dinamicamente uno stile C vettoriale. (. Ho lavorato in C++ per oltre 25 anni , e ho ancora utilizzare new[]) Di solito, se conosco la dimensione davanti, io uso qualcosa di simile:

std::vector<int> data(n); 

a ottenere un vettore già dimensionato, piuttosto che utilizzare push_back.

Naturalmente, se n è molto piccolo ed è noto al momento della compilazione, userò std::array (se ho accesso al C++ 11), o anche un array di stile C, e solo creare l'oggetto in pila, con no allocazione dinamica. (Tali casi sembrano essere rari nel codice su cui lavoro: piccoli array di dimensioni fisse tendono ad essere membri delle classi . Dove utilizzo occasionalmente un array in stile C.)