it-swarm.it

Scelta tra vector :: resize () e vector :: reserve ()

Sto pre-allocando un po 'di memoria alla mia variabile membro vector. Di seguito il codice è una parte minima

class A {
  vector<string> t_Names;
public:
  A () : t_Names(1000) {}
};

Ora a un certo punto del tempo, se t_Names.size() è uguale a 1000. Ho intenzione di aumentare le dimensioni di 100. Quindi, se raggiunge 1100, Aumenta di nuovo di 100 E così via.

La mia domanda è: cosa scegliere tra vector::resize() e vector::reserve(). C'è qualche scelta migliore in questo tipo di scenario?

Modifica: Ho una specie di stima precisa per il t_Names. Stimo che sia tra 700 E 800. Tuttavia in determinate (raramente) situazioni, può crescere più di 1000.

138
iammilind

Le due funzioni fanno cose molto diverse!

Il metodo resize() (e passare l'argomento al costruttore è equivalente a quello) inserirà o cancellerà il numero appropriato di elementi nel vettore per renderlo di dimensioni (ha un secondo argomento opzionale per specificare il loro valore). Interesserà la size(), l'iterazione passerà su tutti quegli elementi, Push_back inserirà dopo di loro e potrai accedervi direttamente usando operator[].

Il metodo reserve() alloca solo la memoria, ma la lascia non inizializzata. Riguarda solo capacity(), ma size() rimarrà invariato. Non esiste alcun valore per gli oggetti, poiché non viene aggiunto nulla al vettore. Se poi inserisci gli elementi, non si verificherà alcuna riallocazione, perché è stato fatto in anticipo, ma questo è l'unico effetto.

Quindi dipende da cosa vuoi. Se si desidera un array di 1000 voci predefinite, utilizzare resize(). Se si desidera un array in cui si prevede di inserire 1000 elementi e si desidera evitare un paio di allocazioni, utilizzare reserve().

EDIT: Il commento di Blastfurnace mi ha fatto rileggere la domanda e rendermi conto che nel tuo caso la risposta corretta è don ' t preallocare manualmente. Continua a inserire gli elementi alla fine di cui hai bisogno. Il vettore verrà riallocato automaticamente in base alle necessità e lo farà altro in modo efficiente rispetto al modo manuale menzionato. L'unico caso in cui reserve() ha senso è quando hai una stima ragionevolmente precisa della dimensione totale di cui avrai bisogno facilmente disponibile in anticipo.

EDIT2: Modifica domanda annuncio: se hai una stima iniziale, allora reserve() quella stima. Se risulta non essere abbastanza, lascia che il vettore faccia la sua cosa.

237
Jan Hudec

resize() non solo alloca la memoria, ma anche crea tante volte quante dimensioni desiderato che passi a resize() come argomento. Ma reserve() alloca solo la memoria, non crea istanze. Questo è,

std::vector<int> v1;
v1.resize(1000); //allocation + instance creation
cout <<(v1.size() == 1000)<< endl;   //prints 1
cout <<(v1.capacity()==1000)<< endl; //prints 1

std::vector<int> v2;
v2.reserve(1000); //only allocation
cout <<(v2.size() == 1000)<< endl;   //prints 0
cout <<(v2.capacity()==1000)<< endl; //prints 1

Output ( demo online ):

1
1
0
1

Quindi resize() potrebbe non essere desiderabile, se non vuoi gli oggetti creati di default. Sarà anche lento. Inoltre, se Push_back() nuovi elementi, il size() del vettore aumenterà ulteriormente allocando nuova memoria (che significa anche spostare l'esistente elementi nello spazio di memoria appena allocato). Se hai usato reserve() all'inizio per assicurarti che ci sia già abbastanza memoria allocata, size() del vettore aumenterà quando Push_back() ad esso, ma non allocherà nuovamente la nuova memoria fino a quando non esaurirà lo spazio riservato .

26
Nawaz

riservare quando non si desidera inizializzare gli oggetti quando riservati. inoltre, potresti preferire differenziare logicamente e tenere traccia del suo conteggio rispetto al conteggio degli usi quando ridimensioni. quindi c'è una differenza comportamentale nell'interfaccia: il vettore rappresenterà lo stesso numero di elementi quando riservato e sarà più grande di 100 elementi quando ridimensionato nel tuo scenario.

C'è qualche scelta migliore in questo tipo di scenario?

dipende interamente dai tuoi obiettivi quando combatti il ​​comportamento predefinito. alcune persone favoriranno gli allocatori personalizzati, ma abbiamo davvero bisogno di un'idea migliore di ciò che stai cercando di risolvere nel tuo programma per consigliarti bene.

in seguito, molte implementazioni vettoriali raddoppieranno semplicemente il numero di elementi allocati quando devono crescere - stai cercando di ridurre al minimo le dimensioni di allocazione dei picchi o stai cercando di riservare spazio sufficiente per qualche programma senza blocco o qualcos'altro?

2
justin

Dalla tua descrizione, sembra che tu voglia "riservare" lo spazio di archiviazione allocato di t_Names vettoriali.

Si noti che resize inizializza il vettore appena allocato in cui reserve alloca ma non costruisce. Quindi, 'riserva' è molto più veloce di 'ridimensiona'

È possibile fare riferimento alla documentazione relativa alla differenza di ridimensionare e riserva

1
dip