pop_back () return value?

¿Por qué pop_back() tiene un valor de retorno? Busqué en Google esto y descubrí que lo hace más eficiente. ¿Es esta la única razón para hacerlo así en el estándar?

Creo que hay algo relacionado con el hecho de que copiar una instancia del último objeto podría arrojar una excepción. Al hacerlo, estás perdiendo tu objeto, ya que pop_back () lo eliminó de tu contenedor. Mejor con unas pocas líneas de código:

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

La eficiencia tiene poco (o nada, realmente) que ver con eso.

Este diseño es el resultado de un importante artículo de Tom Cargill , publicado en los años 90, que levantó bastante las cejas en aquel entonces. IIRC, en él Cargill demostró que es imposible diseñar una función de stack segura segura de excepción.

Es por el principio de separación de consulta de comando .

La eficiencia es una cosa. Otra razón para que pop_back() no devuelva un elemento es una excepción de seguridad.
Si la función pop() devolvió el valor, y el constructor de copia arrojó una excepción, es posible que no pueda garantizar que el contenedor esté en el mismo estado que antes de llamar a pop() .

Puede encontrar más información en los libros de Herb Sutters sobre excepciones. Creo que este tema está cubierto aquí . Pero no estoy seguro.

La razón no es tanto la eficiencia como la seguridad de las excepciones. La clase de contenedor se puede usar para almacenar cualquier tipo de objeto. Sería imposible implementar pop_back () de una manera segura de excepción si la función devolvería el objeto después de eliminarlo del contenedor, ya que devolver el valor del objeto implica la construcción de la copia.

Esta es la implementación real de vector :: pop_back () en la biblioteca estándar GNU C ++:

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

Esto es lo que se vería si devolviera el último elemento al final:

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

Esto implica dos construcciones de copia, en la statement save = back() y al devolver una copia del objeto. No hay garantías de que la expresión de retorno no genere una excepción después de que el elemento se haya destruido del contenedor.

Bueno, ¿cuántos motivos tiene que haber?

Esto evita la copia potencialmente costosa del objeto cuando solo desea eliminarlo del contenedor. C ++ tiene la filosofía de no pagar por lo que no necesita.

¿Por qué devolvería el valor? Siempre puede acceder al valor en cualquier momento antes de pop_back no es necesario que pop_back proporcione esta funcionalidad.