2010-11-15 9 views
11

Considerare:È consentito std :: vector :: push_back di lanciare per qualsiasi ragione diversa dalla riallocazione o costruzione fallita?

std::vector<int> v; 
v.reserve(1); 
v.push_back(1); // is this statement guaranteed not to throw? 

ho scelto int perché non ha costruttori che potrebbero gettare - ovviamente se qualche copia costruttore della T getta, quindi tale eccezione sfugge vector<T>::push_back.

Questa domanda vale tanto per insert come push_back, ma è stato ispirato da Is it safe to push_back 'dynamically allocated object' to vector?, che avviene per chiedere di push_back.

Nello standard C++ 03 e C++ 0x/FCD, le descrizioni di vector::insert affermano che se non avviene alcuna riallocazione, gli iteratori/riferimenti prima del punto di inserimento rimangono validi. Loro non dicono affermano che se non avviene alcuna riallocazione, non viene lanciata alcuna eccezione (a meno che dai costruttori ecc. Di T).

C'è qualcosa altrove nello standard per garantire questo?

Non mi aspetto che push_back esegua tutto ciò che potrebbe generare in questo caso. L'implementazione GNU no. La domanda è se lo standard lo proibisca.

Come follow-up, qualcuno può pensare a un motivo per cui qualsiasi implementazione dovrebbe essere lanciata? Il meglio che posso pensare, è che se una chiamata a reserve aumenta la capacità ad un valore superiore a max_size(), allora insert è forse possibile lanciare length_error quando la dimensione massima viene superata. Sarebbe inutile aumentare la capacità oltre lo max_size(), ma non vedo immediatamente nulla che lo impedisca, o [Modifica: il tuo allocatore probabilmente ti impedirebbe di aumentare la capacità oltre max_size, quindi questo suggerimento potrebbe non essere valido.]

+1

Esclusione di costruttori di copia che potrebbero generare durante push_back? – Flexo

+0

@awoodland: Steve sta specificatamente utilizzando 'int's per rimuovere quella dal tavolo –

+0

@awoodland: sì, e come dice John ho scelto un esempio specifico che ignora tutto ciò, per semplicità. –

risposta

1

Bene , dipende dall'allocatore che stai usando.

A parte l'allocatore, l'unica cosa che si può fare affidamento su è che push_back() e push_front() sono garantiti per essere noop se viene generata un'eccezione (23,1-10). Lo standard sicuramente non vieta al push_back() di lanciare eccezioni.

+0

@Let_Me_Be: dipende dall'allocatore in che modo? In effetti stai dicendo che 'push_back' (e presumibilmente ogni altra funzione di qualsiasi contenitore) può effettuare chiamate arbitrarie all'allocatore che potrebbe generare, anche quando non si riassegna? Probabilmente dovrei parlare di 'Alloc :: construct' piuttosto che di costruttori di T, ma penso che un allocatore che getta in' construct' quando il costruttore rilevante di T non lo farebbe, sta comunque violando lo standard. Non mi interessa cosa succede nei programmi non conformi :-) –

+0

@Steve Bene, lo standard parla esplicitamente del fatto che insert/push_back sono noops quando viene lanciata un'eccezione (diversa dal costruttore o dall'assegnazione di T). D'altra parte, la riallocazione dovrebbe avvenire solo quando la nuova dimensione è maggiore della vecchia capacità. Non ha senso gettare nulla, ma è ovviamente permesso. –

+0

Anche questo è un mio pensiero, è permesso da quelle clausole sull'inserto. Quindi, l'unica cosa che potrebbe proibirlo, sono le altre 781 pagine dello standard ;-) Per esempio, se ci fosse qualche affermazione generale su quando i vettori possono lanciare. Non mi aspetto certo alcuna dichiarazione generale sui contenitori o sulle sequenze, dal momento che 'deque' e' list' non hanno capacità, quindi per loro 'push_back' deve sempre essere autorizzato ad allocare memoria. –

Problemi correlati