2010-03-31 8 views
3
list<int> foo; 
list<int> foo2; 
list<int>::iterator foo_end = foo.end(); 
list<int>::iterator foo2_end = foo2.end(); 

for (list<int>::iterator it = foo.begin(); it != foo2_end; ++foo) <- notice != comparison here 
{ 
    ... 

cela a-t-il permis? cela fonctionnera-t-il correctement?comparaison de deux itérateurs end()

Je suis enclin à penser que cela dépend de l'implémentation, quelqu'un sait si la norme en dit quelque chose?

Répondre

7

Un défaut a été signalé à ce sujet (LWG defect 446). Le rapport de défaut demandait s'il était valable de comparer des itérateurs qui se réfèrent à des éléments de différents conteneurs. Les notes dans le rapport de défaut expliquent que c'était certainement l'intention de le faire est indéfini, mais il n'est pas explicitement déclaré qu'il est indéfini.

La résolution proposée est d'ajouter ce qui suit à la norme, indiquant explicitement qu'il est indéfini:

Le résultat de l'évaluation directement ou indirectement une fonction de comparaison ou binaire - opérateur avec deux valeurs iterator comme arguments qui ont été obtenus à partir de deux plages différentes r1 et r2 (y compris leurs valeurs passées) qui ne sont pas des sous-plages d'une plage commune sont indéfinies, sauf indication contraire explicite.

Edit: Cette langue ne figure pas dans le C++ 0x FCD. Ce problème a en fait été résolu par des changements dans N3066; spécifiquement l'addition suivante (§24.2.5/2):

Le domaine de == pour itérateurs à terme est celui d'itérateurs au cours de la même séquence sous-jacente.

2

Oui il est permis (à savoir compilera).
Non cela ne fonctionnera pas correctement.

foo2_end des points à la fin de foo2, non foo, de sorte que votre iterator commencera au début et à la fin de foo lorsqu'il atteint la fin de foo2, qui ne sera jamais, parce que vous itérez foo. Une fois que it a passé la fin de foo, vous obtenez une erreur de segmentation. Note: J'ai supposé que vous vouliez écrire ++it, pas ++foo.

1

Il se compilera mais entraînera une erreur de segmentation. Les itérateurs sont spécifiques aux objets, et comparer deux itérateurs d'objets différents donnera toujours une inégalité. Ainsi, l'expression it != foo2_end sera toujours évaluée à true, et votre programme se bloquera lorsque it atteindra foo.end() et vous tenterez de le déréférencer.

+0

Cela dépend de l'implémentation des itérateurs. Une implémentation triviale, et pas vraiment bonne, d'un itérateur de liste pourrait être un pointeur dans le nœud, avec une identification nulle après la fin (qui est un idiome commun) [peut-être un pointeur dans la liste est requis pour une opération], avec l'égalité étant définie comme une comparaison directe des adresses de nœuds référencées. Il n'y a rien dans la norme qui rendrait cette mise en œuvre non conforme. –

+0

Assez juste, même si je suppose que les compilateurs de qualité commerciale seraient un peu plus intelligents à ce sujet.Après tout, rendre les interfaces faciles à utiliser correctement et difficile à utiliser est un bon objectif commun. :) –

+0

@ DavidRodríguez-dribeas "(une) implémentation d'un itérateur de liste pourrait être un pointeur dans le nœud, avec une identification nulle après la fin (qui est un idiome commun)" pourriez-vous citer une telle liste std :: cassée la mise en oeuvre? – curiousguy