web-dev-qa-db-fra.com

Pourquoi préférerais-je utiliser le vecteur pour déque

Puisque

  1. ce sont deux conteneurs de mémoire contigus;
  2. en ce qui concerne les fonctionnalités, deque a presque tout ce que le vecteur a mais plus, car il est plus efficace d'insérer à l'avant.

Pourquoi quelqu'un préfère-t-il std::vector à std::deque?

75
Leon

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 .

103
phooji

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).

deque a ses plus grands avantages:

  1. Lors de la croissance ou de la réduction de la collection de chaque côté
  2. Lorsque vous avez affaire à de très grandes tailles de collection.
  3. Lorsque vous traitez avec des bools et que vous voulez vraiment des bools plutôt qu'un jeu de bits.

Le second d'entre eux est moins connu, mais pour les très grandes tailles de collection:

  1. Le coût de la réaffectation est important
  2. La surcharge de devoir trouver un bloc de mémoire contigu est restrictive, donc vous pouvez manquer de mémoire plus rapidement.

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 ...)

31
CashCow

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.

26
Howard Hinnant

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

6
Erik

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.)

2
patrickvacek

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.

0
George Gaál

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é:

  • Push_back est fondamentalement le même pour tous
  • insérer, effacer en deque sont beaucoup plus rapides que la liste et légèrement plus rapides que le vecteur

Quelques réflexions supplémentaires, et une note à considérer circulaire_buffer.

0
Nick Westgate

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.

0
Sean

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.

0
BenGoldberg