c++ - valor - ¿Por qué no emplace/_front/_back devuelve una referencia?
vector c++ español (5)
Dos argumentos para elegir esta firma:
API de simetría. Estas API son simétricas con pop_back, pop_front y push y pop como implementadas para colas. Estas funciones (las funciones emergentes) tienen una situación en la que un elemento puede perderse en presencia de una excepción (es decir, el elemento se elimina de la colección, pero antes de que se devuelva, se produce una excepción (por ejemplo, si el constructor del objeto puede lanzar).
Al implementar esta funcionalidad (elemento de lectura y elemento pop) como dos funciones separadas, ambas pueden implementarse de manera transaccional.
SRP . Es una buena guía de diseño, que si describe el comportamiento de una función y necesita usar la palabra "y", ha roto el SRP y probablemente debería dividirlo en dos (es decir, una función que "agrega un elemento al final y devuelve una referencia a él "probablemente debe escribirse como dos funciones", agregue un elemento al final "y" devuelva el elemento al final ", ambos pueden ofrecer al menos garantías de excepción débiles para el código del cliente.
No estoy seguro de si se aplicaron estos criterios para el diseño, pero recuerdo el argumento de garantía de excepción dado en una conferencia sobre seguridad de excepciones.
Cuando std::vector
s, std::list
s (u otros contenedores STL), a menudo escribo esto, por falta de código (en lugar de poner el vec[index]
explícito cada vez) y la eficiencia de asignación de memoria (evitando una copia / mover), y supongo que no soy el único que hace eso:
std::vector<A> vec;
vec.emplace_back();
A &element = vec[vec.size()-1];
element.prop = "value";
¿Por qué los métodos emplace_front
, emplace_back
y emplace_front
contenedores STL no devuelven un T&
? Le permitiría a uno simplemente escribir esto en lugar de usar un vec.size()-1
sombrío:
std::vector<A> vec;
A &element = vec.emplace_back();
element.prop = "value";
Esto se ha corregido en C++17 . Tu ejemplo
std::vector<A> vec;
A &element = vec.emplace_back();
element.prop = "value";
Es válido el código C ++ 17.
No lo necesitas. Escribe esto:
template<class C, class...Args>
auto emplace_back(C& c, Args&&...args)->decltype(c.back()){
c.emplace_back(std::forward<Args>(args)...);
return c.back();
}
y tiene la semántica que desea sin tener que modificar la interfaz del contenedor.
Sólo:
emplace_back(vec).prop = "foo";
Tiene métodos de miembro para acceder a esos objetos, ya que sabe dónde se han insertado. Es decir, front()
y back()
.
Algunas otras funciones (por ejemplo, map::insert
) devolverían un iterador porque no sabe cómo acceder al elemento insertado en tiempo constante . En el caso del emplace
, lo sabes.
Otra razón para no devolver nada podría ser el rendimiento (la mayoría de las veces, no usaría el valor devuelto). Y en C ++, pagas por lo que usas.
en c ++ 11 puedes usar:
m.emplace(val1, val2).first
para obtener una referencia al iterador devuelto, entonces:
m.emplace(val1, val2).first->first
y
m.emplace(val1, val2).first->second
para acceder al mapa de k y v
:)