Ich iteriere über einen Vektor und benötige den Index, auf den der Iterator gerade zeigt. AFAIK Dies kann auf zwei Arten geschehen:
it - vec.begin()
std::distance(vec.begin(), it)
Was sind die Vor- und Nachteile dieser Methoden?
c++
iterator
coding-style
Kairol
quelle
quelle
it
?std::container_type::iterator it;
std::list
bietet keinen direkten Zugriff auf Elemente anhand ihrer Position. Wenn Sie dies nicht könnenlist[5]
, sollten Sie dies nicht könnenlist.begin() + 5
.Ich würde es vorziehen,
std::distance(vec.begin(), it)
da ich den Container ohne Codeänderungen ändern kann. Wenn Sie sich beispielsweise für die Verwendung entscheiden,std::list
anstattstd::vector
einen Iterator mit wahlfreiem Zugriff bereitzustellen, wird Ihr Code weiterhin kompiliert. Da std :: distance die optimale Methode in Abhängigkeit von den Iteratormerkmalen aufnimmt, treten auch keine Leistungseinbußen auf.quelle
vec
ist eine schlechte Nachricht. Wenn der Code so umgeschrieben wurde, dass er generisch ist und den Containertyp als Vorlagenparameter verwendet, können (und sollten) wir über den Umgang mit Iteratoren mit nicht wahlfreiem Zugriff sprechen ;-)vec
ist auch eine ziemlich schlechte Nachricht.Wie UncleBens und Naveen gezeigt haben, gibt es für beide gute Gründe. Welches "besser" ist, hängt davon ab, welches Verhalten Sie möchten: Möchten Sie ein Verhalten mit konstanter Zeit garantieren oder möchten Sie, dass es bei Bedarf auf die lineare Zeit zurückgreift?
it - vec.begin()
nimmt konstante Zeit inoperator -
Anspruch, ist jedoch nur für Iteratoren mit wahlfreiem Zugriff definiert, sodass der Code beispielsweise mit Listeniteratoren überhaupt nicht kompiliert wird.std::distance(vec.begin(), it)
funktioniert für alle Iteratortypen, ist jedoch nur dann eine Operation mit konstanter Zeit, wenn sie für Iteratoren mit wahlfreiem Zugriff verwendet wird.Keiner ist "besser". Verwenden Sie diejenige, die das tut, was Sie brauchen.
quelle
Ich mag dieses:
it - vec.begin()
weil es mir klar sagt "Distanz vom Anfang". Bei Iteratoren sind wir es gewohnt, arithmetisch zu denken, daher ist das-
Vorzeichen hier der klarste Indikator.quelle
distance
?it++
und nicht so etwasstd::increment(it)
, nicht wahr? Würde das nicht auch als weniger klar gelten?++
Operator wird als Teil der STL-Sequenzen definiert, wie wir den Iterator inkrementieren.std::distance
berechnet die Anzahl der Elemente zwischen dem ersten und dem letzten Element. Die Tatsache, dass der-
Bediener arbeitet, ist nur ein Zufall.Wenn Sie Ihren Algorithmus bereits auf die Verwendung von a
std::vector::iterator
undstd::vector::iterator
only beschränkt / fest codiert haben , spielt es keine Rolle, welche Methode Sie am Ende verwenden werden. Ihr Algorithmus ist bereits über den Punkt hinaus konkretisiert, an dem die Auswahl eines der beiden einen Unterschied machen kann. Beide machen genau das Gleiche. Es ist nur eine Frage der persönlichen Präferenz. Ich persönlich würde explizite Subtraktion verwenden.Wenn Sie andererseits einen höheren Grad an Allgemeinheit in Ihrem Algorithmus beibehalten möchten, nämlich die Möglichkeit zuzulassen, dass er eines Tages auf einen anderen Iteratortyp angewendet wird, hängt die beste Methode von Ihrer Absicht ab . Dies hängt davon ab, wie restriktiv Sie in Bezug auf den hier verwendeten Iteratortyp sein möchten.
Wenn Sie die explizite Subtraktion verwenden, wird Ihr Algorithmus auf eine ziemlich enge Klasse von Iteratoren beschränkt: Iteratoren mit wahlfreiem Zugriff. (Das bekommen Sie jetzt von
std::vector
)Wenn Sie verwenden
distance
, unterstützt Ihr Algorithmus eine viel breitere Klasse von Iteratoren: Eingabeiteratoren.Natürlich ist die Berechnung
distance
für Iteratoren mit nicht wahlfreiem Zugriff im Allgemeinen eine ineffiziente Operation (während sie für solche mit wahlfreiem Zugriff ebenso effizient ist wie die Subtraktion). Es liegt an Ihnen, zu entscheiden, ob Ihr Algorithmus für Iteratoren mit nicht wahlfreiem Zugriff in Bezug auf die Effizienz sinnvoll ist . Wenn der daraus resultierende Effizienzverlust so verheerend ist, dass Ihr Algorithmus völlig unbrauchbar wird, sollten Sie sich besser an die Subtraktion halten, um ineffiziente Verwendungen zu verhindern und den Benutzer zu zwingen, nach alternativen Lösungen für andere Iteratortypen zu suchen. Wenn die Effizienz mit Iteratoren ohne wahlfreien Zugriff immer noch im nutzbaren Bereich liegt, sollten Siedistance
die Tatsache verwenden und dokumentieren, dass der Algorithmus mit Iteratoren mit wahlfreiem Zugriff besser funktioniert.quelle
Laut http://www.cplusplus.com/reference/std/iterator/distance/ verwendet die Distanzmethode den Operator , da
vec.begin()
es sich um einen Iterator mit wahlfreiem Zugriff handelt-
.Die Antwort ist also aus Sicht der Leistung dieselbe, aber vielleicht ist die Verwendung
distance()
einfacher zu verstehen, wenn jemand Ihren Code lesen und verstehen müsste.quelle
Ich würde die
-
Variantestd::vector
nur für verwenden - es ist ziemlich klar, was gemeint ist, und die Einfachheit der Operation (die nicht mehr als eine Zeigersubtraktion ist) wird durch die Syntax ausgedrückt (distance
auf der anderen Seite klingt sie wie Pythonagoras auf der erste Lesung, nicht wahr?). Wie UncleBen hervorhebt,-
fungiert es auch als statische Behauptung, fallsvector
versehentlich auf geändert wirdlist
.Ich denke auch, dass es viel häufiger vorkommt - ich habe jedoch keine Zahlen, die dies beweisen. Hauptargument:
it - vec.begin()
ist im Quellcode kürzer - weniger Schreibarbeit, weniger Platzbedarf. Da es klar ist, dass die richtige Antwort auf Ihre Frage Geschmackssache ist, kann dies auch ein gültiges Argument sein.quelle
Hier ist ein Beispiel, um "alle" Vorkommen von 10 zusammen mit dem Index zu finden. Ich dachte, das wäre hilfreich.
quelle