2011-04-06 16 views

Respuesta

45

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.

7

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.

+3

Específicamente, considere cambiar a 'std :: deque <>' si necesita '' pop_front() 'rápido. – ildjarn

+0

"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. –

+0

Dejé la asignación en este ejemplo porque el usuario estaba hablando de reventar. Tienes razón, sin embargo. – orlp

1

Probablemente porque sería monumentalmente lento para vectores grandes.

pop_front() en un vector que contiene 1000 objetos requeriría 999 operator=() llamadas.

+0

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

+0

@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

0

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

+6

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 void pop_front (std :: vector & v) {v.pop_back(); } – MSalters

+0

Tu comentario me parece incorrecto. Al hacer 'template void pop_front (std :: vector & v) {v.pop_back(); } 'no eliminará el elemento esperado' front'. Mi sugerencia es "intercambiar" elementos de "frente" y "de regreso" y eliminar el último. – marchelbling

+0

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

13

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.

6

Simple. Solo intente:

vec.erase(vec.begin()); 
Cuestiones relacionadas