¿Por qué no hay un método pop_front
en C++ std::vector
?¿Por qué no hay un método pop_front en C++ std :: vector?
Respuesta
Porque un std::vector
no tiene ninguna característica particular con respecto a la inserción de elementos en la parte delantera, a diferencia de algunos otros contenedores. La funcionalidad provista por cada contenedor tiene sentido para ese contenedor.
Probablemente debería utilizar un std::deque
, que es explícitamente buena a insertar en la parte delantera y espalda.
Verificar this diagram salir.
Porque push_back
y pop_back
son operaciones especiales para un vector que solo requiere el cómputo O(1)
. Cualquier otro push o pop toma O(n)
.
Esto no es un "error" o un "capricho", esto es solo una propiedad del contenedor de vectores. Si necesita una pop_front rápida, considere cambiar a otro contenedor.
Probablemente porque sería monumentalmente lento para vectores grandes.
pop_front()
en un vector que contiene 1000 objetos requeriría 999 operator=()
llamadas.
No hay nada más lento que 'borrar (v.begin())'. Esto se debe a que los vectores no tienen propiedades especiales para empujar al principio, opuestos a empujar al final (o reventar). – orlp
@nightcracker - True, erase() es igual de malo. ¡Y acepto que querer pop_front() en un vector es un buen "olor" que está usando el tipo de contenedor incorrecto! – Roddy
Sin embargo, si necesita un pop_front y no se preocupan por el índice de los elementos en el vector, se puede hacer tipo de un pop_front con algo como
template<typename T>
void pop_front(std::vector<T>& vec)
{
vec.front() = vec.back();
vec.pop_back();
}
Dan Higgins habla de esto también: https://youtu.be/oBbGC-sUYVA?t=2m52s
Sería un caso raro en el que a ambos les importó o no les importó el orden de los elementos. Porque si realmente no te importa, esto es aún más fácil: template
Tu comentario me parece incorrecto. Al hacer 'template
Además, si utiliza un vector cuando no le interesan demasiado los elementos, puede haber un orden si desea manipular un búfer continuo de memoria. No estoy discutiendo si esta es una buena idea o no, pero en este caso muy específico (y específico), es una forma válida de hacer un 'pop_front' en O (1). – marchelbling
vector se implementa normalmente algo como esto:
struct
{
T* begin; // points to the first T in the vector
T* end; // points just after the last T in the vector
int capacity; // how many Ts of memory were allocated
};
"begin" sirve como "puntero a la primera T en el vector" y "apunta a toda la memoria que asignamos". por lo tanto, es imposible "sacar" elementos de la parte frontal del vector simplemente incrementando "comenzar": haga esto y ya no tendrá un puntero a la memoria que necesita desasignar. eso derramaría memoria. por lo que un "frente pop" necesitaría copiar todos los Ts desde la parte posterior del vector al frente del vector, y eso es comparativamente lento. entonces decidieron dejarlo fuera del estándar.
lo que quiere decir algo como esto:
struct
{
T* allocated; // points to all the memory we allocated
T* begin; // points to the first T in the vector
T* end; // points just after the last T in the vector
int capacity; // how many Ts of memory were allocated
};
con esto, se puede "pop_front" moviendo "comenzar" adelante y hacia atrás sin peligro de olvidar la memoria que quiere desasignar más tarde. ¿Por qué std :: vector no funciona de esta manera? Supongo que fue una cuestión de gusto entre los que escribieron el estándar. su objetivo era probablemente proporcionar el "arreglo dinámicamente redimensionable" más simple posible, y creo que tuvieron éxito.
Simple. Solo intente:
vec.erase(vec.begin());
- 1. manera rápida de implementar pop_front a std :: vector
- 2. por qué no hay ningún vector para encontrar en C++
- 3. ¿Por qué no hay un método Convert.toFloat()?
- 4. ¿Por qué no hay std :: stou?
- 5. ¿Por qué no puedo push_back un unique_ptr en un vector?
- 6. Regreso std :: vector por valor
- 7. sizeof() std :: vector (C++)
- 8. std :: list threading push_back, front, pop_front
- 9. std :: vector versus std :: array en C++
- 10. ¿Por qué no se define main `main (std :: vector <std::string> args)`?
- 11. ¿Por qué no puedo indexar un std :: vector en la ventana inmediata?
- 12. ¿Por qué std :: vector :: operator [] 5 a 10 veces más rápido que std :: vector :: at()?
- 13. ¿Por qué no hay vector (tamaño_tipo n, const Allocator & alloc) en C++ 11?
- 14. C++ std :: pair, std :: vector y memcopy
- 15. ¿Por qué no hay ningún algoritmo std :: copy_if?
- 16. ¿Cómo puedo ordenar un std :: vector por los valores de un std :: vector diferente?
- 17. por qué no hay un método de eliminación en HttpWebResponse
- 18. ¿Por qué no hay método Service.onStop?
- 19. qué espacio de nombres con anteponer ::, por ejemplo :: std :: vector
- 20. ¿Por qué no podemos declarar un std :: vector <AbstractClass>?
- 21. ¿Cómo funciona C++ std :: vector?
- 22. ¿Por qué es diferente el comportamiento C++ initializer_list para std :: vector y std :: array?
- 23. cómo liberar std :: vector si no hay memoria del montón
- 24. std :: vector alternativa para C
- 25. ¿Puede un std :: vector ser = 'd a otro std :: vector?
- 26. ¿Por qué std :: cin.getline no tiene un método oveloaded para tomar std :: string?
- 27. ¿Por qué no hay ReverseEnumerator en C#?
- 28. cargando fstreams en un std :: vector en C++
- 29. ¿Por qué un std :: vector no puede tomar un tipo local?
- 30. Convertir std :: vector en matriz
Específicamente, considere cambiar a 'std :: deque <>' si necesita '' pop_front() 'rápido. – ildjarn
"requiere solo O (1) cálculo" - O (1) amortizado en el caso de "push_back", el peor de los casos es Theta (n) cuando tiene que reasignar porque no ha reservado el espacio. –
Dejé la asignación en este ejemplo porque el usuario estaba hablando de reventar. Tienes razón, sin embargo. – orlp