2016-06-01 23 views

risposta

8

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 di capacity() allora tutti gli iteratori e riferimenti (tra cui l'iteratore past-the-end) sono invalidate. Altrimenti solo l'iteratore passato-fine viene invalidato.

+0

@KerrekSB Pensi che la descrizione su cppreference non sia accurata? (Dovrebbe essere risolto?) – songyuanyao

+3

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. –

+1

In realtà, le specifiche sono complete e a tenuta d'aria, sono distribuite su alcune sezioni. Vedi la mia risposta aggiornata. –

30

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 di capacity().

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à.

+0

Sembra un altro elemento di comportamento specificato. – NathanOliver

+2

@NathanOliver: In realtà va bene, solo un po 'sparsi. Vedi l'aggiornamento. –

+0

@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