Je suis nouveau dans le langage C ++. J'ai commencé à utiliser des vecteurs, et j'ai remarqué que dans tout le code que je vois pour itérer à travers un vecteur via des indices, le premier paramètre de la for
boucle est toujours quelque chose basé sur le vecteur. En Java, je pourrais faire quelque chose comme ça avec une ArrayList:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
Y a-t-il une raison pour laquelle je ne vois pas cela en C ++? Est-ce une mauvaise pratique?
c++
coding-style
for-loop
iterator
Flynn
la source
la source
std::vector<int>::size_type i = 0;
, cependant, ou peutstd::vector<int>::iterator it = vector.begin();
- être ?std::vector
? , le Q réel demandé ici est: Y a - t-il une raison pour laquelle je ne vois pas ceci en C ++? Est-ce une mauvaise pratique? aka Pourquoi est-ce que je vois toujours du code en C ++ qui utilise des itérateurs lors de l'itérationstd::vector
?Réponses:
Non. Ce n'est pas une mauvaise pratique, mais l'approche suivante rend votre code une certaine flexibilité .
Habituellement, pré-C ++ 11, le code d'itération sur les éléments de conteneur utilise des itérateurs, quelque chose comme:
C'est parce que cela rend le code plus flexible.
Tous les conteneurs de bibliothèque standard prennent en charge et fournissent des itérateurs. Si, à un stade ultérieur du développement, vous devez basculer vers un autre conteneur, ce code n'a pas besoin d'être modifié.
Remarque: L'écriture de code qui fonctionne avec tous les conteneurs de bibliothèques standard possibles n'est pas aussi facile que cela puisse paraître.
la source
auto
.La raison pour laquelle vous ne voyez pas une telle pratique est assez subjective et ne peut pas avoir de réponse définitive, car j'ai vu de nombreux codes qui utilisent la méthode que vous avez mentionnée plutôt que le
iterator
code de style.Voici quelques raisons pour lesquelles les gens ne considèrent pas la
vector.size()
manière de boucler:size()
chaque fois dans la condition de boucle. Cependant, soit c'est un non-problème, soit cela peut être résolu de manière trivialestd::for_each()
à lafor
boucle elle-mêmestd::vector
à un autre (par exemplemap
,list
) , il faudra aussi le changement du mécanisme en boucle, car pas tout le soutien récipientsize()
style de boucleC ++ 11 fournit une bonne facilité pour se déplacer dans les conteneurs. Cela s'appelle «boucle basée sur la plage pour» (ou «boucle for améliorée» en Java).
Avec peu de code, vous pouvez parcourir le plein (obligatoire!)
std::vector
:la source
#pragma omp parallel for
.La manière la plus propre d'itérer à travers un vecteur est via les itérateurs:
ou (équivalent à ce qui précède)
Avant C ++ 0x, vous devez remplacer auto par le type d'itérateur et utiliser des fonctions membres au lieu des fonctions globales de début et de fin.
C'est probablement ce que vous avez vu. Par rapport à l'approche que vous évoquez, l'avantage est que vous ne dépendez pas beaucoup du type de
vector
. Si vous passezvector
à une autre classe de «type collection», votre code fonctionnera probablement toujours. Cependant, vous pouvez également faire quelque chose de similaire en Java. Il n'y a pas beaucoup de différence conceptuellement; C ++, cependant, utilise des modèles pour implémenter cela (par rapport aux génériques en Java); par conséquent, l'approche fonctionnera pour tous les types pour lesquelsbegin
et desend
fonctions sont définies, même pour les types non-classe tels que les tableaux statiques. Voir ici: Comment fonctionne la fonction basée sur la plage pour les tableaux simples?la source
begin
etend
, cependant, est une ligne unique.auto
d'un autre côté, ce serait assez délicat.La bonne façon de faire est de:
Où T est le type de la classe à l'intérieur du vecteur. Par exemple, si la classe était CActivity, écrivez simplement CActivity au lieu de T.
Ce type de méthode fonctionnera sur chaque STL (pas seulement les vecteurs, ce qui est un peu mieux).
Si vous souhaitez toujours utiliser des index, la méthode est la suivante:
la source
std::vector<T>::size_type
toujourssize_t
? C'est le type que j'utilise toujours pour ça.Il y a quelques bonnes raisons d'utiliser des itérateurs, dont certaines sont mentionnées ici:
Changer de conteneur ultérieurement n'invalide pas votre code.
c'est-à-dire que si vous passez d'un std :: vector à un std :: list, ou std :: set, vous ne pouvez pas utiliser d'indices numériques pour obtenir votre valeur contenue. L'utilisation d'un itérateur est toujours valide.
Interception à l'exécution d'une itération non valide
Si vous modifiez votre conteneur au milieu de votre boucle, la prochaine fois que vous utiliserez votre itérateur, il lèvera une exception d'itérateur non valide.
la source
J'ai été surpris que personne n'ait mentionné que l'itération dans un tableau avec un index entier vous permet d'écrire facilement du code défectueux en indiquant un tableau avec le mauvais index. Par exemple, si vous avez des boucles imbriquées utilisant
i
etj
comme index, vous pouvez indiquer de manière incorrecte un tableau avecj
plutôt quei
et ainsi introduire une erreur dans le programme.En revanche, les autres formes répertoriées ici, à savoir la
for
boucle basée sur la plage et les itérateurs, sont beaucoup moins sujettes aux erreurs. La sémantique du langage et le mécanisme de vérification de type du compilateur vous empêcheront d'accéder accidentellement à un tableau en utilisant le mauvais index.la source
Avec STL, les programmeurs utilisent
iterators
pour traverser les conteneurs, car l'itérateur est un concept abstrait, implémenté dans tous les conteneurs standard. Par exemple,std::list
n'a pasoperator []
du tout.la source
L'utilisation de l'opérateur automatique le rend vraiment facile à utiliser car on n'a pas à se soucier du type de données et de la taille du vecteur ou de toute autre structure de données
Vecteur d'itération utilisant la boucle automatique et for
Production:
Vous pouvez également utiliser cette méthode pour itérer des ensembles et des listes. L'utilisation de auto détecte automatiquement le type de données utilisé dans le modèle et vous permet de l'utiliser. Donc, même si nous avions un
vector
desstring
ouchar
la même syntaxe fonctionnera bienla source
La manière correcte d'itérer la boucle et d'imprimer ses valeurs est la suivante:
la source
Voici un moyen plus simple d'itérer et d'imprimer des valeurs en vecteur.
la source
la source