Pourquoi il n'y a pas de pop_front
méthode en C++ std::vector
?
Parce qu'un std::vector
n'a pas de particularité concernant l'insertion d'éléments à l'avant, contrairement à certains autres conteneurs. La fonctionnalité fournie par chaque conteneur est logique pour ce conteneur .
Vous devriez probablement utiliser un std::deque
, ce qui est explicitement bon à insérer à l'avant et à l'arrière .
Vérifiez ce diagramme out.
Simple. Essayez simplement:
vec.erase(vec.begin());
vecteur est généralement implémenté quelque chose comme ceci:
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" sert à double titre de "pointeur sur le premier T du vecteur" et de "pointeur sur toute la mémoire que nous avons allouée". par conséquent, il est impossible de "faire sauter" des éléments sur le devant du vecteur en incrémentant simplement "begin" - faites-le et vous n'avez plus de pointeur sur la mémoire dont vous avez besoin pour désallouer. cela ferait fuir la mémoire. donc un "pop_front" devrait copier tous les Ts de l'arrière du vecteur vers l'avant du vecteur, et c'est relativement lent. ils ont donc décidé de le laisser hors de la norme.
ce que vous voulez, c'est quelque chose comme ceci:
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
};
avec cela, vous pouvez "pop_front" en déplaçant "begin" en avant et en arrière sans risque d'oublier quelle mémoire désallouer plus tard. pourquoi std :: vector ne fonctionne-t-il pas de cette façon? je suppose que c'était une question de goût parmi ceux qui ont écrit la norme. leur objectif était probablement de fournir le "tableau redimensionnable dynamiquement" le plus simple possible, et je pense qu'ils ont réussi.
Parce que Push_back
Et pop_back
Sont des opérations spéciales pour un vecteur qui ne nécessitent que le calcul de O(1)
. Tout autre push ou pop prend O(n)
.
Ce n'est pas un "bug" ou une "bizarrerie", c'est juste une propriété du conteneur vectoriel. Si vous avez besoin d'un pop_front rapide, envisagez de passer à un autre conteneur.
Probablement parce que ce serait monumentalement lent pour les grands vecteurs.
pop_front()
sur un vecteur contenant 1000 objets nécessiterait 999 operator=()
appels.
Cependant, si vous avez besoin d'un pop_front et ne vous souciez PAS de l'index des éléments dans le vecteur, vous pouvez faire sorte de un pop_front avec quelque chose comme
template<typename T>
void pop_front(std::vector<T>& vec)
{
vec.front() = vec.back();
vec.pop_back();
}
Dan Higgins en parle aussi: https://youtu.be/oBbGC-sUYVA?t=2m52s