Réponses:
Je préférerais it - vec.begin()
précisément pour la raison opposée donnée par Naveen: donc ce ne serait pas compilerait donc si vous changez le vecteur en liste. Si vous faites cela à chaque itération, vous pourriez facilement finir par transformer un algorithme O (n) en un algorithme O (n ^ 2).
Une autre option, si vous ne sautez pas dans le conteneur pendant l'itération, serait de conserver l'index comme deuxième compteur de boucle.
Note: it
est un nom commun pour un itérateur conteneur, std::container_type::iterator it;
.
it
?
std::container_type::iterator it;
std::list
n'offre pas d'accès direct aux éléments par leur position, donc si vous ne pouvez pas le faire list[5]
, vous ne devriez pas pouvoir le faire list.begin() + 5
.
Je préférerais std::distance(vec.begin(), it)
car cela me permettra de changer le conteneur sans aucun changement de code. Par exemple, si vous décidez d'utiliser std::list
au lieu de celui std::vector
qui ne fournit pas d'itérateur d'accès aléatoire, votre code sera toujours compilé. Puisque std :: distance choisit la méthode optimale en fonction des traits de l'itérateur, vous n'aurez pas non plus de dégradation des performances.
vec
est une mauvaise nouvelle. Si le code a été réécrit pour être générique, en prenant le type de conteneur comme paramètre de modèle, c'est alors que nous pouvons (et devons) parler de la gestion des itérateurs à accès non aléatoire ;-)
vec
est également une très mauvaise nouvelle.
Comme l'ont montré UncleBens et Naveen, il y a de bonnes raisons pour les deux. Laquelle est "meilleure" dépend du comportement que vous souhaitez: voulez-vous garantir un comportement à temps constant, ou voulez-vous qu'il revienne au temps linéaire si nécessaire?
it - vec.begin()
prend un temps constant, mais operator -
n'est défini que sur les itérateurs à accès aléatoire, de sorte que le code ne compilera pas du tout avec les itérateurs de liste, par exemple.
std::distance(vec.begin(), it)
fonctionne pour tous les types d'itérateurs, mais ne sera une opération à temps constant que si elle est utilisée sur des itérateurs à accès aléatoire.
Aucun des deux n'est "meilleur". Utilisez celui qui fait ce dont vous avez besoin.
J'aime celui-ci:, it - vec.begin()
parce que pour moi, il dit clairement "distance depuis le début". Avec les itérateurs, nous sommes habitués à penser en termes d'arithmétique, donc le -
signe est l'indicateur le plus clair ici.
distance
?
it++
et pas quelque chose comme std::increment(it)
ça, non? Cela ne serait-il pas aussi moins clair?
++
opérateur est défini dans le cadre des séquences STL comme la façon dont nous incrémentons l'itérateur. std::distance
calcule le nombre d'éléments entre le premier et le dernier élément. Le fait que l' -
opérateur travaille n'est qu'une coïncidence.
Si votre algorithme est déjà limité / codé en dur pour utiliser un std::vector::iterator
et std::vector::iterator
seulement, peu importe la méthode que vous finirez par utiliser. Votre algorithme est déjà concrétisé au-delà du point où le choix de l'un peut faire la différence. Ils font tous les deux exactement la même chose. C'est juste une question de préférence personnelle. J'utiliserais personnellement une soustraction explicite.
Si, d'autre part, vous souhaitez conserver un degré de généralité plus élevé dans votre algorithme, à savoir, pour permettre la possibilité qu'un jour à l'avenir, il puisse être appliqué à un autre type d'itérateur, la meilleure méthode dépend de votre intention. . Cela dépend de la façon dont vous souhaitez être restrictif en ce qui concerne le type d'itérateur qui peut être utilisé ici.
Si vous utilisez la soustraction explicite, votre algorithme sera limité à une classe d'itérateurs plutôt étroite: les itérateurs à accès aléatoire. (C'est ce que vous obtenez maintenant std::vector
)
Si vous utilisez distance
, votre algorithme prendra en charge une classe beaucoup plus large d'itérateurs: les itérateurs d'entrée.
Bien entendu, le calcul distance
pour les itérateurs à accès non aléatoire est en général une opération inefficace (tandis que, pour les accès aléatoires, il est aussi efficace que la soustraction). C'est à vous de décider si votre algorithme a un sens pour les itérateurs à accès non aléatoire, en termes d'efficacité. Si la perte d'efficacité qui en résulte est dévastatrice au point de rendre votre algorithme complètement inutile, alors vous devriez mieux vous en tenir à la soustraction, interdisant ainsi les utilisations inefficaces et forçant l'utilisateur à rechercher des solutions alternatives pour d'autres types d'itérateurs. Si l'efficacité des itérateurs à accès non aléatoire est toujours dans la plage utilisable, vous devez utiliser distance
et documenter le fait que l'algorithme fonctionne mieux avec les itérateurs à accès aléatoire.
Selon http://www.cplusplus.com/reference/std/iterator/distance/ , puisqu'il vec.begin()
s'agit d'un itérateur à accès aléatoire , la méthode de la distance utilise l' -
opérateur.
Donc, la réponse est, du point de vue des performances, c'est la même chose, mais peut-être que l'utilisation distance()
est plus facile à comprendre si quelqu'un doit lire et comprendre votre code.
Je n'utiliserais la -
variante que pour std::vector
- c'est assez clair ce que l'on veut dire, et la simplicité de l'opération (qui n'est pas plus qu'une soustraction de pointeur) est exprimée par la syntaxe ( distance
, de l'autre côté, sonne comme pythagore sur le première lecture, non?). Comme le souligne UncleBen, -
agit également comme une assertion statique en cas de vector
modification accidentelle enlist
.
Je pense aussi que c'est beaucoup plus courant - mais je n'ai pas de chiffres pour le prouver. Argument principal: it - vec.begin()
est plus court dans le code source - moins de travail de frappe, moins d'espace consommé. Comme il est clair que la bonne réponse à votre question se résume à une question de goût, cela peut également être un argument valable.
Voici un exemple pour trouver "toutes" les occurrences de 10 avec l'index. Je pensais que cela serait d'une certaine aide.
void _find_all_test()
{
vector<int> ints;
int val;
while(cin >> val) ints.push_back(val);
vector<int>::iterator it;
it = ints.begin();
int count = ints.size();
do
{
it = find(it,ints.end(), 10);//assuming 10 as search element
cout << *it << " found at index " << count -(ints.end() - it) << endl;
}while(++it != ints.end());
}