dev compiler c++ c++11

compiler - c++14



¿Por qué no se pudo sobrecargar push_back para hacer el trabajo de emplace_back? (2)

Aquí hay otro ejemplo.

Honestamente, los dos son semánticamente tan diferentes, que su comportamiento similar debe considerarse como una mera coincidencia (debido al hecho de que C ++ tiene "constructores de copia" con una sintaxis particular).

Realmente no emplace_back usar emplace_back menos que quieras una semántica de construcción en el lugar .
Es raro que necesites tal cosa. Generalmente push_back es lo que realmente quieres, semánticamente.

#include <vector> struct X { X(struct Y const &); }; struct Y { Y(int const &); operator X(); }; int main() { std::vector<X> v; v. push_back(Y(123)); // Calls Y::operator X() and Y::Y(int const &) v.emplace_back(Y(123)); // Calls X::X(Y const &) and Y::Y(int const &) }

En primer lugar, soy consciente de esta pregunta , pero no creo que esté preguntando lo mismo.

Sé lo que hace std::vector<T>::emplace_back , y entiendo por qué lo usaría sobre push_back() . Utiliza plantillas variadic que me permiten enviar múltiples argumentos al constructor de un nuevo elemento.

Pero lo que no entiendo es por qué el comité estándar de C ++ decidió que era necesaria una nueva función de miembro. ¿Por qué no podrían simplemente extender la funcionalidad de push_back() . Por lo que puedo ver, push_back podría estar sobrecargado en C ++ 11 para ser:

template <class... Args> void push_back(Args&&... args);

Esto no rompería la compatibilidad hacia atrás, mientras que le permite pasar N argumentos, incluidos los argumentos que invocarían un valor normal o un constructor de copia. De hecho, la implementación de GCC C ++ 11 de push_back() simplemente llama a emplace_back de todos modos:

void push_back(value_type&& __x) { emplace_back(std::move(__x)); }

Entonces, tal como lo veo, no hay necesidad de emplace_back() . Todo lo que necesitaban para agregar era una sobrecarga para push_back() que acepta argumentos variadic y reenvía los argumentos al constructor del elemento.

¿Estoy equivocado aquí? ¿Hay alguna razón para que una función completamente nueva fuera necesaria aquí?


Si T tiene un constructor de conversión explícito, hay un comportamiento diferente entre emplace_back y push_back .

struct X { int val; X() :val() {} explicit X(int v) :val(v) {} }; int main() { std::vector<X> v; v.push_back(123); // this fails v.emplace_back(123); // this is okay }

Hacer el cambio que sugieres significaría que push_back sería legal en esa instancia, y supongo que ese no fue el comportamiento deseado. No sé si esta es la razón, pero es lo único que se me ocurre.