Duplicata possible:
Pourquoi utiliser des itérateurs au lieu des indices de tableau?
string::iterator it;
for (it = str.begin(); it < str.end(); it++)
cout << *it;
cout << endl;
Pourquoi pas:
for (int i = 0; i < str.size(); i++)
cout << str[i];
cout << endl;
Il semble que string :: iterator ne fournit pas non plus de vérification de plage. Pourquoi devrions-nous utiliser string::iterator
plutôt que d'indexer?
Merci.
L'index ne peut être utilisé que pour les conteneurs qui prennent en charge l'accès aléatoire - accès direct à une position donnée.
L'itérateur offre un moyen unifié d'accéder à n'importe quelle structure de collecte/données. La flexibilité lors de la refactorisation de votre code est immense.
Les itérateurs sont une interface standard. En utilisant des itérateurs, vous pouvez utiliser les mêmes algorithmes avec différents conteneurs. La décision finale de les utiliser ou non vous appartient en fonction de la convivialité et de la lisibilité.
Par exemple, en utilisant l'algorithme de transformation standard pour convertir std::string
en majuscules:
std::string str = "A String";
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
se traduira par str
étant égal à "A STRING"
.
Pour std :: string en particulier, je vous suggère d'utiliser des index car il prend en charge l'accès aléatoire et son plus simple de cette façon. La seule raison pour laquelle il est "recommandé" d'utiliser des itérateurs est que les itérateurs offrent une interface standard pour accéder aux séquences, de sorte que si votre séquence est changée en std :: list par exemple, votre code d'itération ne sera pas affecté.
Duplicata de:
Cela dit, c'est une question de générosité. Vous pouvez faire un lot davantage avec les itérateurs utilisant STL qu'avec l'accès aux tableaux. De plus, si vous devez refactoriser le code et changer la chaîne en un vecteur, une liste ou corde , vous n'aurez pas du tout à réécrire votre code.
Enfin, il y a la question de la sécurité dans l'itération. Si vous souhaitez accéder au caractère NEXT dans votre boucle, avec les itérateurs, vous pouvez le faire en toute sécurité, mais l'augmentation de l'indice du tableau peut segfault sur vous le dernier élément, donc besoin d'un autre contrôle.
Comme indiqué dans cette question , la méthode size () n'est pas garantie d'être O (1)
Dans les cas où vous ne savez pas sur quelle classe vous itérez (car il s'agit d'un argument de modèle), vous devez utiliser un itérateur car toutes les classes qui fournissent un itérateur ne fournissent pas également []
(et pas toutes les classes qui fournissent []
, en fournit un qui fonctionne en O(1) fois). Ainsi, en utilisant l'itérateur, vous vous assurerez que la fonction fonctionnera avec autant de classes que possible (mais pas avec les tableaux C).
Dans ce cas précis, je ne vois aucune raison de préférer l'un à l'autre, sauf une préférence personnelle ou peut-être une optimisation prématurée.
Les deux œuvres.
La raison principale serait la cohérence: vous parcourez une collection ou les caractères d'une chaîne de la même manière, en demandant un itérateur et en le faisant avancer.
Je ne dirais pas les détails de mise en œuvre de ++it
résultant en un incrément de pointeur par rapport à str[i]
impliquant l'arithmétique des pointeurs mérite d'être mentionnée. Et la vérification de la plage est également un détail d'implémentation.
Les itérateurs sont plus sûrs et offrent plus de flexibilité comme publié par quelqu'un d'autre. De plus, un index ne peut être utilisé que pour les conteneurs qui supportent (efficacement) accès aléatoire (c'est-à-dire l'accès direct à un élément à une position donnée) Un itérateur est un concept plus général. Les itérateurs offrent une traversée efficace des listes liées, des fichiers et d'un certain nombre d'autres structures de données. Cela conduit souvent à la génération de code plus efficace .
Je suppose qu'une autre raison pour laquelle les itérateurs devraient être préférés aux indices est que toutes les collections ne prennent pas en charge l'accès aléatoire à temps constant.
Par exemple, si vous voulez l'élément n - e dans une liste chaînée, vous devez parcourir tous les éléments précédents (avec les indices 0 ..n-1) jusqu'à ce que vous obteniez à l'élément n - e. (Cette opération prend du temps linéaire.)
Un itérateur (séquentiel) se souvient où il se trouve dans une collection et n'a pas toujours à recommencer depuis le début lorsque vous voulez l'élément suivant. Dans votre exemple, vous n'avez pas réellement besoin d'accéder aux caractères d'une chaîne dans un ordre aléatoire, mais uniquement de manière séquentielle, donc l'utilisation d'un itérateur sera presque certainement plus rapide (temps constant).