web-dev-qa-db-fra.com

Accéder aux éléments d'un vecteur en C ++?

J'ai souvent trouvé que les gens utilisent les crochets de tableau [] et une fonction vectorielle normale .at (). Pourquoi y a-t-il deux méthodes distinctes? Quels sont les avantages et les inconvénients des deux? Je sais que .at () est plus sûr, mais y a-t-il des situations où .at () ne peut pas être utilisé? Et si .at () est toujours plus sûr, pourquoi utiliser des crochets de tableau [].

J'ai cherché autour mais je n'ai pas pu trouver une question similaire. Si une question comme celle-ci existe déjà, veuillez me la transmettre et je supprimerai cette question.

35
fdh

std::vector::at() vous protège contre l'accès aux éléments du tableau en dehors des limites en lançant une exception out_of_bounds contrairement à l'opérateur [] qui ne prévient ni ne lance d'exceptions lors d'un accès au-delà des limites du vecteur.

std::vector Est/était considéré comme un remplacement/construction c ++ pour les tableaux à longueur variable (VLA) en c99. Pour que les tableaux de style c soient facilement remplaçables par std::vector, Il fallait que les vecteurs fournissent une interface similaire à celle d'un tableau, donc le vecteur fournit l'opérateur [] Pour accéder à ses éléments. Dans le même temps, le comité des normes C++ a peut-être également ressenti le besoin de fournir une sécurité supplémentaire pour std::vector Sur les tableaux de style c et, par conséquent, il a également fourni la méthode std::Vector::at() qui le fournit.

Naturellement, la méthode at() vérifie la taille du vecteur avant de le déréférencer et ce sera un peu de surcharge (peut-être négligeable dans la plupart des cas d'utilisation) par rapport à l'accès aux éléments par [], Donc std::vector Vous offre les deux options pour être en sécurité ou pour être plus rapide au détriment de la gestion de la sécurité vous-même.

51
Alok Save

Comme d'autres l'ont mentionné, at() effectue la vérification des limites et [] ne fait pas. Deux raisons pour lesquelles je peux penser à préférer [] sont:

  1. Syntaxe plus propre
  2. Performance. Lorsque vous parcourez les éléments d'un vecteur, il est souvent excessif et très coûteux d'effectuer une vérification des limites à chaque itération.
12
Jason B

at()

Avantages:

  • sûr car une exception est levée si le tableau est hors limites

Les inconvénients:

  • accès lent
  • plus de caractères à taper

operator[]

Avantages:

  • accès rapide en raison de contrôles des limites manquantes
  • moins de caractères à taper
  • accès aux éléments de tableau "intuitif"

Les inconvénients:

  • dangereux en raison de contrôles des limites manquantes
10
Frank

choix personnel

La raison pour laquelle certaines personnes utilisent l'opérateur d'indice est qu'elles sont intuitives car un vecteur est similaire à un tableau accédant aux éléments de cette façon.

Certaines personnes préfèrent le [], Et d'autres préfèrent la .at(), c'est un choix personnel.

Le choix technique

En supposant que vous ne parlez que d'accès, la fonction .at() vérifie les limites et lève une exception lorsque vous essayez d'accéder à un élément au-delà des limites. La fonction est "plus sûre", mais si vous gérez vous-même les limites, n'hésitez pas à utiliser l'opérateur d'indice!

C'est vraiment à vous de choisir le style d'accessoire que vous utilisez!

2
CStreel

Vous avez raison .at () est plus sûr car il vérifiera les limites du tableau. L'opérateur [] ignore la vérification et n'est pas défini si vous effectuez un accès illégal.

L'accès traditionnel aux tableaux en C/C++ n'a jamais eu de vérification des limites des tableaux, et dans les années 90 avant Java a été introduit, beaucoup pensaient que cela ajouterait des frais généraux inacceptables. Je crois que, en général, c'est ce n'est pas vrai aujourd'hui, et ce n'était pas aussi vrai que beaucoup le croyaient à l'époque non plus. Je suis sûr qu'il y a des cas où cela compte, mais en général, vous feriez mieux de commencer en toute sécurité et de changer si vous trouvez un besoin impérieux de faites-le.

2
Bill

L'opérateur d'indice a moins de saisie impliqué, ce qui rend le code plus clair. De plus, le refactoring vers/depuis un tableau C vient naturellement.

1
Seva Alekseyev

J'utilise STLPort 5.2. Semble at() fait une vérification de plage.

référence at(size_type __n) { _M_range_check(__n); return (*this)[__n]; }

1
Prabhu