Quiero saber cuáles son las diferencias entre vectorlas funciones push_backy insert.
¿Existe alguna diferencia estructural?
¿Existe una diferencia de rendimiento realmente grande?
Respuestas:
La mayor diferencia es su funcionalidad. push_backsiempre pone un nuevo elemento al final del vectory le insertpermite seleccionar la posición del nuevo elemento. Esto impacta el desempeño. vectorlos elementos se mueven en la memoria solo cuando es necesario aumentar su longitud porque se le asignó muy poca memoria. Por otro lado insertobliga a mover todos los elementos después de la posición seleccionada de un nuevo elemento. Simplemente tienes que hacerle un lugar. Es por eso insertque a menudo puede ser menos eficiente que push_back.
push_back.
insertestá realmente en el end(), por lo que habrá más ramas adentro insertque adentro push_back, a menos que el compilador pueda darse cuenta de que en realidad no son necesarias.
Las funciones tienen diferentes propósitos. vector::insertle permite insertar un objeto en una posición específica en el vector, mientras vector::push_backque simplemente pegará el objeto al final. Vea el siguiente ejemplo:
using namespace std;
vector<int> v = {1, 3, 4};
v.insert(next(begin(v)), 2);
v.push_back(5);
// v now contains {1, 2, 3, 4, 5}
Puede utilizar insertpara realizar el mismo trabajo que push_backcon v.insert(v.end(), value).
Además del hecho, que push_back(x)hace lo mismo que insert(x, end())(quizás con un rendimiento ligeramente mejor), hay varias cosas importantes que debe saber sobre estas funciones:
push_backsolo existe en BackInsertionSequencecontenedores, por lo que, por ejemplo, no existe en set. No podría porque push_back()te garantiza que siempre se agregará al final.FrontInsertionSequencey lo han hecho push_front. Esto es satisfecho por deque, pero no por vector.insert(x, ITERATOR)es de InsertionSequence, que es común para sety vector. De esta forma, puede utilizar seto vectorcomo destino para múltiples inserciones. Sin embargo, settiene además insert(x), que hace prácticamente lo mismo (esta primera inserción setsignifica solo para acelerar la búsqueda del lugar apropiado comenzando desde un iterador diferente, una característica que no se usa en este caso).Tenga en cuenta sobre el último caso que si va a agregar elementos en el ciclo, entonces hacer container.push_back(x)y container.insert(x, container.end())hará efectivamente lo mismo. Sin embargo, esto no será cierto si obtiene esto container.end()primero y luego lo usa en todo el ciclo.
Por ejemplo, podría arriesgarse al siguiente código:
auto pe = v.end();
for (auto& s: a)
v.insert(pe, v);
Esto efectivamente copiará todo aal vvector, en orden inverso , y solo si tiene la suerte de no reasignar el vector para la extensión (puede evitarlo llamando reserve()primero); si no tiene tanta suerte, obtendrá el llamado UndefinedBehavior (tm). En teoría, esto no está permitido porque los iteradores del vector se consideran invalidados cada vez que se agrega un nuevo elemento.
Si lo haces de esta manera:
copy(a.begin(), a.end(), back_inserter(v);
se copiará aal final de ven el orden original, y esto no conlleva el riesgo de invalidación del iterador.
[EDITAR] Hice anteriormente que este código se viera de esta manera, y fue un error porque en inserterrealidad mantiene la validez y el avance del iterador:
copy(a.begin(), a.end(), inserter(v, v.end());
Entonces, este código también agregará todos los elementos en el orden original sin ningún riesgo.
insertermantiene el avance y la validez del iterador. Tendré que editar la publicación :)
insertpuede hacerlo en cualquier lugar e incluye otras cosas como soporte de rangos.push_backes más conveniente para agregar al final.