2010-01-03 3 views
31

Mögliche Duplizieren:
Why use iterators instead of array indices?Warum verwenden Sie string :: iterator statt index?

string::iterator it; 
for (it = str.begin(); it < str.end(); it++) 
    cout << *it; 
cout << endl; 

Warum nicht:

for (int i = 0; i < str.size(); i++) 
    cout << str[i]; 
cout << endl; 

es, dass string :: iterator scheint nicht entweder Bereichsprüfung bieten. Warum sollten wir string::iterator statt Index verwenden?

Danke.

+13

Die Frage ist, warum würdest du 'cout << str << endl;' nicht benutzen. – avakar

+6

@jcyang: Stellen Sie, abgesehen von den Antworten anderer, sicher, dass Sie die Angewohnheit haben, die Vorinkrementierung mit Iteratoren in Schleifen zu verwenden. d.h. benutze ++ es und nicht es ++. Das Pre-Inkrement erstellt keine unnötigen Provisorien. – Jagannath

+5

Zusätzlich zu Jagannaths Kommentar, bevorzugen Sie 'operator! =()' Over 'operator <()', wenn Sie einen Iterator mit 'end()' vergleichen. – jason

Antwort

22

Der Index kann nur für Container verwendet werden, die einen wahlfreien Zugriff unterstützen - direkten Zugriff auf eine bestimmte Position.

Der Iterator bietet eine einheitliche Möglichkeit für den Zugriff auf jede Sammlung/Datenstruktur. Die Flexibilität beim Refactoring Ihres Codes ist immens.

-2

In C++ können Sie viele Dinge auf viele verschiedene Arten tun. Dies ist ein weiteres Beispiel. In diesem Fall gibt es keinen Unterschied, welche Methode zu verwenden ist. Im Allgemeinen sind Iteratoren jedoch schneller, sicherer und bieten mehr Flexibilität bei verschiedenen Arten von Containern.

0

Beide funktioniert.

Der Hauptgrund wäre Konsistenz: Sie durchlaufen die Auflistung oder die Zeichen eines Strings auf die gleiche Weise, indem Sie einen Iterator anfordern und ihn voranbringen.

Ich würde nicht sagen, die Implementierungsdetails von ++it, was zu einem Zeiger Inkrement im Vergleich zu str[i] mit Zeiger Arithmetik ist erwähnenswert. Und Bereichsprüfung sind auch Implementierungsdetails.

1

Wie angegeben in this question, size() Methode nicht O sein garantiert ist (1)

+1

Es scheint unklar von diesem Thread. Ein Kommentar erwähnt, dass 'end.-s.begin()' definitiv konstante Komplexität hat, also müsste man verrückt sein, size() mit einer schlechteren Komplexität zu implementieren. – UncleBens

+0

Warum? Die Größe kann auf strlen() - ähnlich wie O (stringLength) basieren. Um size() in O (1) zu implementieren, benötigen Sie Speicher ... – Drakosha

+2

s.size() kann nicht mit einem strlen() - omel erzeugt werden, da std :: string ein beliebiges Zeichen enthalten kann (einschließlich ''\ 0''). Außerdem muss die Zeichenfolge verfolgen, wo sie endet (oder ihre Größe). Warum würdest du am Ende() denken und die Iteratoren wären besser, wenn der String seine Länge nicht kennen würde und das Ende in O (N) finden müsste? – UncleBens

16

Iteratoren eine Standardschnittstelle sind. Mithilfe von Iteratoren können Sie die gleichen Algorithmen mit anderen Containern verwenden. Die endgültige Entscheidung, ob Sie sie verwenden oder nicht, hängt von Ihrer Benutzerfreundlichkeit und Lesbarkeit ab.

beispielsweise unter Verwendung des Standard-Transformationsalgorithmus std::string in Großbuchstaben umzuwandeln:

std::string str = "A String"; 
std::transform(str.begin(), str.end(), str.begin(), ::toupper); 

in str führen gleich "A STRING" ist.

+0

Was ist mit dem spezifischen string :: iterator? Gibt es irgendwelche Vorteile, zum Beispiel? – Jichao

+0

@jcyang: Nur wenn Sie Iteratoren verwenden, dann funktioniert es überall dort, wo Iteratoren erwartet werden, und die Zeichenfolge kann in ein char-Array oder einen Vektor oder einen anderen Container geändert werden, und Ihre Schleife funktioniert weiterhin. – jalf

+0

Im obigen Beispiel gibt die Methode 'std :: string :: begin()' einen 'std :: string :: iterator 'zurück, wie bei' std :: string :: end() '. Der Vorteil ist, dass Sie den 'std :: transform'-Algorithmus verwenden können. Sie können es nicht mit Indizes verwenden. –

0

Iteratoren sind sicherer und Flexibilität bieten, wie von jemandem anderen geschrieben too.In nur einen Index additon kann für Behälter, die (effizient) Unterstützung Zufall Zugang (dh direkter Zugriff auf ein Element in einer bestimmten Position) verwendet werden, Ein Iterator ist ein allgemeineres Konzept. Iteratoren bieten ein effizientes Traversieren von verknüpften Listen, Dateien und einer Reihe anderer Datenstrukturen. Es führt oft zur Erzeugung von effizienter Code.

+4

Iteratoren sind nicht schneller. Jeder Test, den sie jemals gemacht haben, zeigt an, dass sie etwas langsamer sind. –

+0

Danke, ich habe meinen Beitrag korrigiert. –

1

In Fällen, in denen Sie nicht wissen, über welche Klasse Sie iterieren (weil es ein Template-Argument ist), sollten Sie einen Iterator verwenden, da nicht jede Klasse, die einen Iterator bereitstellt, (und nicht jede Klasse) bereitstellt bieten [], bietet eine, die in O (1) Zeit arbeitet). Durch die Verwendung von Iterator stellen Sie sicher, dass die Funktion mit so vielen Klassen wie möglich funktioniert (nicht jedoch mit C-Arrays).

In diesem speziellen Fall sehe ich keinen Grund, einen über den anderen zu bevorzugen, außer persönliche Vorlieben oder vielleicht vorzeitige Optimierung.

0

Ich gehe davon aus, dass ein weiterer Grund, warum Iteratoren gegenüber Indizes vorzuziehen sind, darin besteht, dass nicht alle Sammlungen einen wahlfreien Zugriff mit konstanter Zeit unterstützen.

Zum Beispiel, wenn Sie das n -te Element in einer verknüpften Liste wollen, müssen Sie alle vorhergehenden Elemente zu durchlaufen (mit Indizes 0 .. n-1), bis Sie zum bekommen n - th Element. (Dieser Vorgang dauert linear.)

Ein (sequenzieller) Iterator merkt sich, wo er sich in einer Sammlung befindet und muss nicht immer von vorne beginnen, wenn Sie das nächste Element wünschen. In Ihrem Beispiel müssen Sie nicht wirklich auf die Zeichen in einer Zeichenfolge in zufälliger Reihenfolge zugreifen, sondern nur sequenziell, sodass die Verwendung eines Iterators mit hoher Wahrscheinlichkeit schneller ist (konstante Zeit).

2

Duplizieren von:

  1. Iterators.. why use them?
  2. Why use iterators instead of array indices?

Das heißt, es ist eine Frage der Generizität. Sie können ein Los mehr mit Iteratoren mit STL als mit Array-Zugriff tun. Wenn Sie Code umgestalten und die Zeichenfolge in einen Vektor, eine Liste oder rope ändern müssen, müssen Sie Ihren Code überhaupt nicht neu schreiben.

Schließlich gibt es die Frage der Sicherheit in Iteration. Wenn Sie auf das NEXT-Zeichen in Ihre Schleife zugreifen möchten, könnten Sie dies mit Iteratoren sicher tun, aber wenn Sie das Array-Subskript erhöhen, könnte es beim letzten Element zu einem Fehler kommen.

+2

Der Versuch, auf das nächste Zeichen in einer Schleife zuzugreifen (Dereferenzierung), ist bei Iteratoren nicht sicherer als bei Array-Indizes! Beide benötigen eine Überprüfung, um sicherzustellen, dass Sie nicht bereits am Ende der Zeichenfolge sind. –

5

Für std :: string würde ich vorschlagen, dass Sie Indizes verwenden, da es Random Access unterstützt und einfacher ist. Der einzige Grund, warum Iteratoren "empfohlen" werden, besteht darin, dass Iteratoren eine Standardschnittstelle für den Zugriff auf Sequenzen bieten. Wenn Ihre Sequenz beispielsweise in std :: list geändert wird, bleibt Ihr Iterationscode unbeeinflusst

+0

Beachten Sie auch, dass Iteratoren für ungültig erklärt werden können, während Indizes dies nicht sind. – musiphil