2010-05-13 7 views
9

Je voudrais obtenir loin la valeur suivante pour l'itérateur STL list mais il n'implémente pas operator+, vector l'a cependant. Pourquoi et comment puis-je obtenir la valeur où je veux?Pourquoi seul l'algorithme random-access-iterator implémente l'opérateur + en C++?

Je pense que je peux le faire si j'appelle operator++ plusieurs fois, mais n'est-ce pas un peu sale?

Ce que je veux faire est la suivante:

list<int> l; 
...omitted... 
list<int>::iterator itr = l.begin() + 3; // but, list iterator does not have 
             // operator+ 

Quelle est la meilleure solution pour ce que je veux?

+2

(Presque) sans rapport: vous devez vous assurer qu'il est possible d'atteindre cette position, sinon vous invoquerez un comportement indéfini. Bien que de 'list :: begin()' c'est facile, dans un cas plus générique, la seule façon de savoir (pour non RandomAccessIterator) la distance avec 'list :: end()' est d'invoquer 'std :: distance' ... O (N) aussi. –

+0

Deux excellentes réponses sur ce sujet. +1 à la communauté! –

Répondre

17

Vous pouvez également utiliser std::next (et prev) ou les équivalents fournis par Boost si vous n'avez pas accès à C++ 11.

list<int>::iterator itr = std::next(l.begin(), 3); 

Justification: std::advance est difficile à utiliser (cela fonctionne par effet secondaire, non pas en retournant une copie).

+2

C'est bon à savoir. Je me suis toujours demandé pourquoi 'std :: advance' fonctionnait par effet secondaire au lieu de fonctionnellement. –

+1

@RSam: J'ai toujours supposé que c'est parce que 'std :: advance' est censé imiter ++ itr ou operator + =, selon le cas. Les algorithmes d'itérateur sont généralement écrits dans ces termes, donc les envelopper a le plus de sens. –

+0

Si vous voulez une copie, vous devez en créer une vous-même. C'est un cas courant en C++. – mschneider

37

Vous voulez utiliser std::advance:

list<int>::iterator itr = l.begin(); 
std::advance(itr, 3); 

advance utilisera operator+ et complète en temps constant si l'itérateur est un accès aléatoire alors qu'il bouclera sur operator++ et complète dans le temps linéaire si l'itérateur n'est pas accès aléatoire .  

La raison de ceci est de vous donner le contrôle sur les exigences de complexité. Si vous vous souciez de la complexité de votre opération, utilisez operator+ et obtenez un temps constant, mais cela ne se compile qu'avec des itérateurs à accès aléatoire. Si vous ne vous souciez pas de la complexité que vous utilisez std::advance qui fonctionnera toujours mais la complexité varie en fonction de l'itérateur.

+3

+1 simple, claire et approfondie. – wilhelmtell