Puisque
Pourquoi quelqu'un préfère-t-il std::vector
à std::deque
?
Les éléments d'un deque
ne sont pas contigus en mémoire; Les éléments vector
sont garantis. Donc, si vous devez interagir avec une bibliothèque C ordinaire qui a besoin de tableaux contigus, ou si vous vous souciez (beaucoup) de la localisation spatiale, vous préférerez peut-être vector
. De plus, comme il existe une comptabilité supplémentaire, les autres opérations sont probablement (légèrement) plus chères que leurs opérations vector
équivalentes. D'un autre côté, l'utilisation de nombreuses/grandes instances de vector
peut entraîner une fragmentation inutile du tas (ralentissement des appels à new
).
En outre, comme indiqué ailleurs sur StackOverflow , il y a plus de bonnes discussions ici: http://www.gotw.ca/gotw/054.htm .
Pour connaître la différence, il faut savoir comment deque
est généralement implémenté. La mémoire est allouée en blocs de tailles égales, et ils sont enchaînés ensemble (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 toujours plus que le vecteur.
vector
fonctionne également bien avec les API qui veulent un tampon contigu car ce sont des API C ou sont plus polyvalentes pour pouvoir prendre un pointeur et une longueur. (Ainsi, vous pouvez avoir un vecteur en dessous ou un tableau régulier et appeler l'API à partir de votre bloc de mémoire).
Où deque
a ses plus grands avantages:
Le second d'entre eux est moins connu, mais pour les très grandes tailles de collection:
Dans le passé, lorsque je traitais de grandes collections et que je passais d'un modèle contigu à un modèle de bloc, nous pouvions stocker une collection environ 5 fois plus grande avant de manquer de mémoire dans un système 32 bits. Cela est dû en partie au fait que lors de la réallocation, il fallait en fait stocker l'ancien bloc ainsi que le nouveau avant de copier les éléments.
Cela dit, vous pouvez avoir des ennuis avec std::deque
sur les systèmes qui utilisent l'allocation de mémoire "optimiste". Alors que ses tentatives pour demander une grande taille de tampon pour une réallocation d'un vector
seront probablement rejetées à un moment donné avec un bad_alloc
, la nature optimiste de l'allocateur est susceptible de toujours accorder la demande pour le plus petit tampon demandé par un deque
et cela est susceptible d'entraîner le système d'exploitation à tuer un processus pour tenter d'acquérir de la mémoire. Celui qu'il choisit peut ne pas être trop agréable.
Les solutions de contournement dans un tel cas consistent à définir des indicateurs au niveau du système pour remplacer l'allocation optimiste (pas toujours faisable) ou à gérer la mémoire un peu plus manuellement, par ex. en utilisant votre propre allocateur qui vérifie l'utilisation de la mémoire ou similaire. Evidemment pas idéal. (Ce qui peut répondre à votre question quant à la préférence du vecteur ...)
J'ai implémenté plusieurs fois vector et deque. deque est extrêmement compliqué du point de vue de la mise en œuvre. Cette complication se traduit par un code plus complexe et plus complexe. Ainsi, vous verrez généralement un hit de taille de code lorsque vous choisissez deque sur vector. 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 le vainqueur incontestable. Mais si vous faites la plupart de vos insertions et effacements à l'arrière, le vecteur sera clairement le gagnant. Lorsque vous n'êtes pas sûr, déclarez votre conteneur avec un typedef (il est donc facile de basculer d'avant en arrière) et mesurez.
std::deque
n'a pas de mémoire continue garantie - et il est souvent un peu plus lent pour l'accès indexé. Un deque est généralement implémenté comme une "liste de vecteurs".
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é de sécurité accès par 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 deque.
(Auparavant, ma réponse a soulevé un manque de normalisation (de la même source que ci-dessus, "les deques peuvent être implémentés par des bibliothèques spécifiques de différentes manières"), mais cela s'applique en fait à peu près n'importe quel type de données de bibliothèque standard.)
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 appuyant sur ces tests.
Je préfère std::deque
À std::vector
Dans la plupart des cas.
Vous ne préféreriez pas que le vecteur soit défini selon ces résultats de test (avec la source).
Bien sûr, vous devez tester dans votre application/environnement, mais en résumé:
Quelques réflexions supplémentaires, et une note à considérer circulaire_buffer.
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.
D'une part, le vecteur est assez souvent juste plus rapide que le deque. Si vous n'avez pas besoin de toutes les fonctionnalités de deque, utilisez un vecteur.
D'autre part, parfois vous avez besoin de fonctionnalités que le vecteur ne vous donne pas, auquel cas vous devez utiliser un deque. Par exemple, je mets au défi quiconque d'essayer de réécrire ce code , sans utiliser de deque, et sans modifier énormément l'algorithme.