Depuis
- ce sont tous les deux des conteneurs de mémoire contigus;
- du point de vue de la fonctionnalité, deque a presque tout ce que le vecteur a mais plus, car il est plus efficace de l'insérer à l'avant.
Pourquoi quelqu'un whould préfère std::vector
à std::deque
?
std::deque
a une très petite taille de bloc maximale (~ 16 octets, si je me souviens bien; peut-être 32), et en tant que telle, elle ne fonctionne pas très bien pour les applications réalistes. Undeque<T>
wheresizeof(T) > 8
(ou 16? C'est un petit nombre) a à peu près les mêmes caractéristiques de performances que avector<T*>
, où chaque élément est alloué dynamiquement. D'autres implémentations ont des tailles de bloc maximales différentes, il est donc difficile d'écrire du code qui a relativement les mêmes caractéristiques de performances sur différentes plates-formesdeque
.Réponses:
Les éléments de a ne
deque
sont pas contigus en mémoire;vector
les éléments sont garantis. Donc, si vous avez besoin d'interagir avec une bibliothèque C simple qui a besoin de tableaux contigus, ou si vous vous souciez (beaucoup) de la localité spatiale, alors vous préférerez peut-êtrevector
. De plus, étant donné qu'il y a une comptabilité supplémentaire, d'autres opérations sont probablement (légèrement) plus chères que leursvector
opérations équivalentes . D'un autre côté, l'utilisation de nombreuses / grandes instances devector
peut entraîner une fragmentation inutile du tas (ralentissant les appels ànew
).De plus, comme indiqué ailleurs sur StackOverflow , il y a d'autres bonnes discussions ici: http://www.gotw.ca/gotw/054.htm .
la source
Pour connaître la différence, il faut savoir comment
deque
est généralement mis en œuvre. La mémoire est allouée en blocs de tailles égales, et ils sont enchaînés (sous forme de tableau ou éventuellement de vecteur).Donc, pour trouver le nième élément, vous trouvez le bloc approprié puis accédez à l'élément qu'il contient. C'est un temps constant, car il s'agit toujours exactement de 2 recherches, mais c'est encore plus que le vecteur.
vector
fonctionne également bien avec les API qui veulent un tampon contigu, car elles sont soit des API C ou sont plus polyvalentes en pouvant prendre un pointeur et une longueur. (Ainsi vous pouvez avoir un vecteur en dessous ou un tableau régulier et appeler l'API depuis votre bloc mémoire).Où
deque
a ses plus grands avantages sont:Le second d'entre eux est moins connu, mais pour de très grandes tailles de collection:
Lorsque je travaillais avec de grandes collections dans le passé et que je passais d'un modèle contigu à un modèle de bloc, nous pouvions stocker environ 5 fois plus grande collection avant de manquer de mémoire dans un système 32 bits. Ceci est en partie dû au fait que, lors de la réallocation, il devait en fait stocker l'ancien bloc ainsi que le nouveau avant de copier les éléments.
Cela dit, vous pouvez avoir des problèmes avec
std::deque
les systèmes qui utilisent une allocation de mémoire «optimiste». Alors que ses tentatives de demander une grande taille de tampon pour une réallocation de avector
seront probablement rejetées à un moment donné avec abad_alloc
, la nature optimiste de l'allocateur est susceptible de toujours accorder la demande pour le plus petit tampon demandé par adeque
et qui est susceptible de provoquer le système d'exploitation pour tuer un processus pour essayer d'acquérir de la mémoire. Celui qu'il choisit n'est peut-être pas trop agréable.Les solutions de contournement dans un tel cas sont soit de définir des indicateurs au niveau du système pour remplacer l'allocation optimiste (pas toujours faisable), soit de gérer la mémoire un peu plus manuellement, par exemple en utilisant votre propre allocateur qui vérifie l'utilisation de la mémoire ou similaire. Évidemment pas idéal. (Ce qui peut répondre à votre question de préférer le vecteur ...)
la source
J'ai implémenté à la fois vector et deque plusieurs fois. deque est beaucoup plus compliqué du point de vue de la mise en œuvre. Cette complication se traduit par plus de code et un code plus complexe. Ainsi, vous verrez généralement une taille de code frappée lorsque vous choisissez deque sur vecteur. Vous pouvez également rencontrer un petit coup de vitesse si votre code utilise uniquement les choses dans lesquelles le vecteur excelle (c'est-à-dire push_back).
Si vous avez besoin d'une file d'attente double, deque est clairement le gagnant. Mais si vous faites la plupart de vos insertions et effacements à l'arrière, le vecteur sera clairement le gagnant. En cas de doute, déclarez votre conteneur avec un typedef (il est donc facile de basculer d'avant en arrière) et mesurez.
la source
vector
.) J'ai écrit une implémentation liée à ci-dessous dans ma réponse . Cela peut être aussi rapide qu'un,vector
mais beaucoup plus largement applicable (par exemple, lors de la création d'une file d'attente rapide).std::deque
n'a pas de mémoire continue garantie - et c'est souvent un peu plus lent pour l'accès indexé. Un deque est généralement implémenté sous la forme d'une "liste de vecteurs".la source
Selon http://www.cplusplus.com/reference/stl/deque/ , "contrairement aux vecteurs, les deques ne sont pas garantis d'avoir tous ses éléments dans des emplacements de stockage contigus, éliminant ainsi la possibilité d'un accès sécurisé grâce à l'arithmétique des pointeurs."
Les Deques sont un peu plus compliqués, en partie parce qu'ils n'ont pas nécessairement une disposition de mémoire contiguë. Si vous avez besoin de cette fonctionnalité, vous ne devez pas utiliser de fichier deque.
(Auparavant, ma réponse évoquait un manque de standardisation (de la même source que ci-dessus, «les deques peuvent être implémentées par des bibliothèques spécifiques de différentes manières»), mais cela s'applique en fait à n'importe quel type de données de bibliothèque standard.)
la source
std::deque
n'est pas moins standardisé questd::vector
. Je ne pense pas que les exigences en matière de complexitéstd::deque
puissent être satisfaites avec un stockage contigu.deque
ne peuvent pas satisfaire avec le stockage contigu?deque
, à savoir que l'insertion aux extrémités ne doit pas invalider les références aux éléments existants. Cette exigence implique une mémoire discontinue.Un deque est un conteneur de séquence qui permet un accès aléatoire à ses éléments, mais il n'est pas garanti d'avoir un stockage contigu.
la source
Je pense que c'est une bonne idée de faire un test de performance de chaque cas. Et prenez une décision en vous basant sur ces tests.
Je préfère
std::deque
questd::vector
dans la plupart des cas.la source
vector
. On peut en déduire que pourquoi pas est un corollaire. Dire que vous préférezdeque
, pour des raisons inconnues, des tests non spécifiés, n'est pas une réponse.Vous ne préférerez pas le vecteur à deque selon ces résultats de test (avec source).
Bien sûr, vous devez tester dans votre application / environnement, mais en résumé:
Quelques réflexions supplémentaires, et une note à prendre en compte circular_buffer.
la source
D'une part, le vecteur est assez souvent plus rapide que deque. Si vous n'avez pas réellement besoin de toutes les fonctionnalités de deque, utilisez un vecteur.
D'autre part, parfois vous faites des caractéristiques des besoins vecteur qui ne vous donne pas, dans ce cas , vous devez utiliser un deque. Par exemple, je mets quiconque au défi d'essayer de réécrire ce code , sans utiliser de deque, et sans modifier énormément l'algorithme.
la source
push_back
etpop_back
,deque<int>
c'est toujours au moins 20% plus rapide quevector<int>
dans mes tests (gcc avec O3). Je suppose que c'est pourquoideque
le choix standard pour des choses commestd::stack
...Notez que la mémoire vectorielle est réaffectée au fur et à mesure que le tableau grandit. Si vous avez des pointeurs vers des éléments vectoriels, ils deviendront invalides.
De plus, si vous effacez un élément, les itérateurs deviennent invalides (mais pas "for (auto ...)").
Edit: changé 'deque' en 'vector'
la source