2010-08-24 4 views
-1

Supposons que nous avons une classe de carte (carte non ordonnée, liste, ensemble, tout ce qui fera aussi). Nous recherchons un élément spécifique. Après avoir appelé le membre find(), nous devons vérifier avec le membre end(). Mais find() sait déjà en interne s'il retourne un bon itérateur ou l'itérateur final. Pourquoi devrions-nous appeler à nouveau end()? Cela ajoute un peu de frais généraux.stl conteneur fin est redondant après trouver, alors quel est le raccourci

std::map<int,float> myMap; 
// some other code to populate the map 
// ... 
std::map<int,float>::iterator myIt; 
myIt = myMap.find(2); // doesn't this already know wheter its returning the end() iterator? 
if (myIt != myMap.end()) { //calling end() here wastes some time because find 
          //already knew the result 
    std::cout << "Found, value is "<<(*myIt).second<<"\n"; 
} else { 
    std::cout << "Not found.\n"; 
} 

Il devrait y avoir un moyen de savoir quel est le résultat de find() sans appeler end().

+6

Vous vous inquiétez probablement trop de la micro-performance. – fredoverflow

+6

Dure le temps en comparaison de quoi? Vous pensez qu'un appel à end() est cher ou quelque chose. Vous pensez que le compilateur n'a peut-être pas ajouté cela pour vous. Quelle autre interface pouvez-vous proposer de plus efficace? –

+8

Avec GCC 4.5 -O2, il n'appelle pas '.end()'. Avec -O3 même le '.find()' est inline. – kennytm

Répondre

1

Des alternatives sont possibles - par exemple, find() pourrait renvoyer une paire std :: ou quelque chose comme boost :: optionnel - mais il y a peu d'avantage pratique et cela nécessite un style de codage plus laid et plus sujet aux erreurs. Dans les langages (principalement interprétés) avec une sentinelle None/null intégrée, c'est la valeur idéale pour cela, mais C++ n'ajoutera pas cela parce qu'il y a un coût important à avoir un bool tagged sur chaque variable, et il est impraticable de dire vouloir stocker ints, écoutez: -78 est ci-après réservé pour end()/Null/quoi que ce soit, s'il vous plaît ne pas en abuser à d'autres fins ". Les classes de conteneur sont dans le meilleur (seulement) endroit pour savoir quelle valeur est une sentinelle appropriée qui n'aurait pas de sens comme un itérateur légal et permet un test trivial, rapide comme l'éclair, ou s'il est nécessaire de virer de bord et d'utiliser structures d'itérateur plus complexes: les résumés end(), qui seront intégrés dans la pratique, atténuent vos problèmes de performance.

7

Quoi d'autre pourrait-il éventuellement retourner? Il doit renvoyer un itérateur valide, mais tout élément autre que end() se référerait à un élément réel dans le conteneur. Il n'y a vraiment pas de choix ici.

En outre, les fonctions STL telles que end() sont généralement intégrées et, en plus de cela, les compilateurs font un peu d'optimisation, de sorte que l'appel supplémentaire n'est pas vraiment un appel.

+0

Lors du profilage de l'un de mes programmes, j'ai remarqué que l'appel end() juste après l'appel find() prenait 20% du temps de find(). C'est donc environ 20% de frais généraux. Je comprends conceptuellement find() renvoie un itérateur valide, mais n'y a-t-il pas un moyen d'économiser sur cette surcharge de 20%? – highBandWidth

+0

J'utilisais GCC 4.2. Merci pour les suggestions -O2 et -O3. Je suis d'accord que c'est une petite micro-performance et pas nécessaire dans 99% des cas. – highBandWidth

+3

@user: Le profilage sans optimisations n'a aucun sens. – fredoverflow

Questions connexes