pop_back () valore di ritorno?

Percpop_back() ha un valore di ritorno? Ho google su questo e ho scoperto che lo rende più efficiente. È questa l’unica ragione per averlo fatto nello standard?

Penso che ci sia qualcosa di correlato al fatto che copiare un’istanza dell’ultimo object potrebbe generare un’eccezione. Quando lo fai, stai perdendo il tuo object, dal momento che pop_back () lo ha rimosso dal tuo contenitore. Meglio con poche righe di codice:

 std::vector holds = {...} ; try { const AnyClass result = holds.pop_back(); // The copy Ctor throw here! } catch (...) { // Last value lost here. } 

L’efficienza ha poco (o niente, davvero) a che fare con esso.

Questo disegno è il risultato di un importante articolo di Tom Cargill , pubblicato negli anni ’90, che ha sollevato un bel po ‘le sopracciglia a quei tempi. IIRC, in esso Cargill ha dimostrato che è imansible progettare una funzione di stack pop eccezionalmente sicura.

È a causa del principio di separazione Comando-query .

L’efficienza è una cosa. Un altro motivo per cui pop_back() non restituisce un elemento è la sicurezza delle eccezioni.
Se la funzione pop() restituito il valore e un’eccezione viene generata dal costruttore di copie, potrebbe non essere ansible garantire che il contenitore si trovi nello stesso stato precedente alla chiamata a pop() .

Puoi trovare maggiori informazioni sui libri di Herb Sutters sulle eccezioni. Penso che questo argomento sia trattato qui . Ma non sono sicuro.

Il motivo non è tanto l’efficienza quanto la sicurezza delle eccezioni. La class contenitore può essere utilizzata per memorizzare qualsiasi tipo di object. Sarebbe imansible implementare pop_back () in modo eccezionalmente sicuro se la funzione restituisse l’object dopo averlo eliminato dal contenitore, poiché la restituzione del valore dell’object implica la costruzione della copia.

Questa è l’effettiva implementazione di vector :: pop_back () nella libreria standard GNU C ++:

  void pop_back() { --this->_M_impl._M_finish; this->_M_impl.destroy(this->_M_impl._M_finish); } 

Questo è come apparirebbe se restituisse l’ultimo elemento alla fine:

  value_type pop_back() { value_type save = back(); --this->_M_impl._M_finish; this->_M_impl.destroy(this->_M_impl._M_finish); return save; } 

Ciò implica due costruzioni di copia, all’istruzione save = back() e alla restituzione di una copia dell’object. Non ci sono garanzie che l’espressione di ritorno non generi un’eccezione dopo che l’elemento è stato distrutto dal contenitore.

Bene, quante ragioni ci devono essere?

Ciò evita la copia potenzialmente costosa dell’object quando si desidera rimuoverlo dal contenitore. C ++ ha la filosofia di non pagare per ciò che non ti serve.

Perché dovrebbe restituire il valore? È sempre ansible accedere al valore in qualsiasi momento prima di pop_back fuori, non è necessario che pop_back fornisca questa funzionalità.