È garantito che std::vector
sposta i propri dati solo quando size()==capacity()
e chiamando push_back()
o emplace_back()
oppure può farlo anche in altro modo?Can std :: vector sposta i suoi dati in un altro indirizzo su emplace_back() anche se c'è spazio ancora non usato in base a capacity()?
risposta
La descrizione dello standard non è abbastanza chiara.
$ 23.3.6.5 vettore modificatori [vector.modifiers]:
Osservazione: Provoca riallocazione se la nuova dimensione è superiore alla vecchia capienza. Se non si verifica alcuna riallocazione, tutti gli iteratori e i riferimenti prima del punto di inserimento rimangono validi.
Così, quando aggiungere elementi a std::vector
riallocazione certamente accadrà quando la nuova dimensione è superiore alla capacità di corrente, ma non dice riallocazione non accadrà anche se il nuovo formato è inferiore o uguale a capacità di corrente . Ad ogni modo, se la riallocazione non avviene, tutti gli iteratori e i riferimenti agli elementi prima che il punto di inserimento debbano rimanere validi, implica che i dati non verranno spostati.
È lo stesso per insert()
, emplace_back()
, emplace()
e push_back()
.
Citazione di cppreference.com solo come riferimento:
Se il nuovo
size()
è maggiore dicapacity()
allora tutti gli iteratori e riferimenti (tra cui l'iteratore past-the-end) sono invalidate. Altrimenti solo l'iteratore passato-fine viene invalidato.
Le specifiche sono un po 'indirette. capacity
viene specificato come:
size_type capacity() const noexcept;
ritorni: Il numero totale di elementi che il vettore può contenere senza richiedere riallocazione.
La seconda parte viene da reserve
:
reserve(size_type n);
Osservazioni: Reallocation invalida tutti i riferimenti, puntatori e iteratori riferimento agli elementi in sequenza. Nessuna riallocazione deve avvenire durante gli inserimenti che si verificano dopo una chiamata a
reserve()
fino al momento in cui un inserimento renderebbe la dimensione del vettore maggiore del valore dicapacity()
.
Da ciò si può concludere che se la dimensione è inferiore alla capacità, quindi l'inserimento non causa la riallocazione.
Non esiste una singola affermazione diretta che il vettore non verrà riallocato se c'è capacità di riserva e non è stato esplicitamente chiamato reserve
. Tuttavia, v'è un requisito contenitore generale [container.requirements.general]:
Se non diversamente specificato (esplicitamente o definendo una funzione in termini di altre funzioni), chiamando una funzione membro contenitore o il superamento di un contenitore come argomento per una funzione di libreria non deve invalidare gli iteratori o modificare i valori di oggetti all'interno di quel contenitore.
Infine, abbiamo descrizione degli effetti di inserimento:
[insert/emplace_back/push_back:]
Osservazioni: Causa riassegnazione se il nuovo formato è maggiore del precedente capacità. Se non avviene alcuna riallocazione, tutti gli iteratori e i riferimenti prima del punto di inserimento rimangono validi.
Mettere tutto insieme: Salvo diversa indicazione, la chiamata di una funzione membro non annulla gli iteratori. La riassegnazione invalida gli iteratori (come descritto come parte di reserve
sopra), quindi, se non diversamente specificato, la chiamata di una funzione membro, e in particolare un inserimento, non viene riallocata. Una specifica di questo tipo viene data per il caso in cui la nuova dimensione supera l'attuale capacità.
Sembra un altro elemento di comportamento specificato. – NathanOliver
@NathanOliver: In realtà va bene, solo un po 'sparsi. Vedi l'aggiornamento. –
@KerrekSB Parliamo di dover ricucire la risposta insieme :) Purtroppo non posso invitarvi di nuovo. Grazie per il tuo tempo e il tuo impegno per incarnare tutto questo. – NathanOliver
@KerrekSB Pensi che la descrizione su cppreference non sia accurata? (Dovrebbe essere risolto?) – songyuanyao
No, sono completamente convinto che l'intenzione sia la capacità di controllare la riallocazione in entrambe le direzioni. È solo una frase leggermente sciatta. Sarebbe altrimenti folle, e probabilmente c'è un sacco di codice del mondo reale che dipende da questo comportamento. –
In realtà, le specifiche sono complete e a tenuta d'aria, sono distribuite su alcune sezioni. Vedi la mia risposta aggiornata. –