insertpuede hacerlo en cualquier lugar e incluye otras cosas como soporte de rangos. push_backes más conveniente para agregar al final.
chris
Respuestas:
93
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.
Por otro lado, insertar al final debería ser tan eficiente como push_back.
Matthieu M.
18
Bueno, casi tan eficiente: el código necesita determinar que el 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.
Yakk - Adam Nevraumont
5
@TomerW La gente elige C o C ++ para poder cuadrar cada ciclo de máquina que puedan, para aumentar el rendimiento, hasta el punto de escribir a veces directamente en ASM ... cada "si" cuenta, esto no es Java ..
Cesar
1
@Cesar No es por qué eliges tu idioma ... cpp puede ser más rápido que c, y viceversa ... demonios, en algunos casos incluso java puede ser más rápido que c para sus optimizaciones de tiempo de ejecución.
Tomer W
@TomerW ho, entonces ¿por qué? iluminame por favor.
Cesar
32
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:
usingnamespacestd;
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.
Algunos envases también pueden satisfacer FrontInsertionSequencey lo han hecho push_front. Esto es satisfecho por deque, pero no por vector.
El 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.
Sus comentarios acerca de que std :: inserter es "arriesgado" para contenedores de tipo vectorial son incorrectos. De hecho, está diseñado para eliminar estos riesgos. Sin orden inverso, sin comportamiento indefinido. Consulte, por ejemplo, fluentcpp.com/2017/10/06/stl-inserter-iterators-work para obtener un desglose.
cuesta abajo desde aquí
Tienes razón. Solo quería acortar el código en lugar de expandirlo en un bucle manual extenso, por lo que en realidad esto no es cierto porque insertermantiene el avance y la validez del iterador. Tendré que editar la publicación :)
insert
puede hacerlo en cualquier lugar e incluye otras cosas como soporte de rangos.push_back
es más conveniente para agregar al final.Respuestas:
La mayor diferencia es su funcionalidad.
push_back
siempre pone un nuevo elemento al final delvector
y leinsert
permite seleccionar la posición del nuevo elemento. Esto impacta el desempeño.vector
los elementos se mueven en la memoria solo cuando es necesario aumentar su longitud porque se le asignó muy poca memoria. Por otro ladoinsert
obliga a mover todos los elementos después de la posición seleccionada de un nuevo elemento. Simplemente tienes que hacerle un lugar. Es por esoinsert
que a menudo puede ser menos eficiente quepush_back
.fuente
push_back
.insert
está realmente en elend()
, por lo que habrá más ramas adentroinsert
que adentropush_back
, a menos que el compilador pueda darse cuenta de que en realidad no son necesarias.Las funciones tienen diferentes propósitos.
vector::insert
le permite insertar un objeto en una posición específica en elvector
, mientrasvector::push_back
que 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
insert
para realizar el mismo trabajo quepush_back
conv.insert(v.end(), value)
.fuente
Además del hecho, que
push_back(x)
hace lo mismo queinsert(x, end())
(quizás con un rendimiento ligeramente mejor), hay varias cosas importantes que debe saber sobre estas funciones:push_back
solo existe enBackInsertionSequence
contenedores, por lo que, por ejemplo, no existe enset
. No podría porquepush_back()
te garantiza que siempre se agregará al final.FrontInsertionSequence
y lo han hechopush_front
. Esto es satisfecho pordeque
, pero no porvector
.insert(x, ITERATOR)
es deInsertionSequence
, que es común paraset
yvector
. De esta forma, puede utilizarset
ovector
como destino para múltiples inserciones. Sin embargo,set
tiene ademásinsert(x)
, que hace prácticamente lo mismo (esta primera inserciónset
significa 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)
ycontainer.insert(x, container.end())
hará efectivamente lo mismo. Sin embargo, esto no será cierto si obtiene estocontainer.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
a
alv
vector, en orden inverso , y solo si tiene la suerte de no reasignar el vector para la extensión (puede evitarlo llamandoreserve()
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:
se copiará
a
al final dev
en 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
inserter
realidad mantiene la validez y el avance del iterador:Entonces, este código también agregará todos los elementos en el orden original sin ningún riesgo.
fuente
inserter
mantiene el avance y la validez del iterador. Tendré que editar la publicación :)