Ich bin neu in der C ++ - Sprache. Ich habe angefangen, Vektoren zu verwenden, und habe festgestellt, dass in dem gesamten Code, den ich sehe, um einen Vektor über Indizes zu iterieren, der erste Parameter der for
Schleife immer auf dem Vektor basiert. In Java könnte ich so etwas mit einer ArrayList machen:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
Gibt es einen Grund, warum ich das in C ++ nicht sehe? Ist es schlechte Praxis?
c++
coding-style
for-loop
iterator
Flynn
quelle
quelle
std::vector<int>::size_type i = 0;
oder vielleichtstd::vector<int>::iterator it = vector.begin();
?std::vector
: Was ist der beste / kürzeste Weg, um darüber zu iterieren ? Das tatsächliche Q, das hier gefragt wird, lautet: Gibt es einen Grund, warum ich dies in C ++ nicht sehe? Ist es schlechte Praxis? aka Warum sehe ich in C ++ immer Code, der beim Durchlaufen Iteratoren verwendetstd::vector
?Antworten:
Nein. Es ist keine schlechte Praxis, aber der folgende Ansatz verleiht Ihrem Code eine gewisse Flexibilität .
Normalerweise verwendet der Code zum Iterieren über Containerelemente vor C ++ 11 Iteratoren, etwa:
Dies liegt daran, dass der Code dadurch flexibler wird.
Alle Standardbibliothekscontainer unterstützen und bieten Iteratoren. Wenn Sie zu einem späteren Zeitpunkt der Entwicklung zu einem anderen Container wechseln müssen, muss dieser Code nicht geändert werden.
Hinweis: Das Schreiben von Code, der mit jedem möglichen Standardbibliothekscontainer funktioniert, ist nicht so einfach, wie es scheint.
quelle
auto
.Der Grund, warum Sie eine solche Praxis nicht sehen, ist ziemlich subjektiv und kann keine eindeutige Antwort haben, da ich viele der Codes gesehen habe, die Ihre erwähnte Methode anstelle von
iterator
Stilcode verwenden.Folgendes kann Gründe dafür sein, dass Menschen nicht über die
vector.size()
Art der Schleife nachdenken:size()
wenn Sie jedes Mal in der Schleifenbedingung anrufen . Entweder ist es kein Problem oder es kann trivial behoben werdenstd::for_each()
Sie diefor
Schleife selbststd::vector
zu anderen (zBmap
,list
) wird auch die Änderung des Schleifenmechanismus verlangen, weil nicht jeder Container Unterstützungsize()
Stil der LoopingC ++ 11 bietet eine gute Möglichkeit, sich durch die Container zu bewegen. Dies wird als "Bereich basierend auf Schleife" (oder "erweitert für Schleife" in Java) bezeichnet.
Mit wenig Code können Sie das Ganze durchlaufen (obligatorisch!)
std::vector
:quelle
#pragma omp parallel for
.Die sauberste Art, einen Vektor zu durchlaufen, sind Iteratoren:
oder (entspricht dem oben genannten)
Vor C ++ 0x müssen Sie auto durch den Iteratortyp ersetzen und Elementfunktionen anstelle der globalen Funktionen begin und end verwenden.
Das haben Sie wahrscheinlich gesehen. Im Vergleich zu dem von Ihnen erwähnten Ansatz besteht der Vorteil darin, dass Sie nicht stark von der Art der abhängig sind
vector
. Wenn Sievector
zu einer anderen Klasse vom Typ "Sammlung" wechseln , funktioniert Ihr Code wahrscheinlich weiterhin. Ähnliches können Sie jedoch auch in Java tun. Konzeptionell gibt es keinen großen Unterschied. C ++ verwendet jedoch Vorlagen, um dies zu implementieren (im Vergleich zu Generika in Java). daher wird der Ansatz für alle Arten arbeiten , für diebegin
undend
Funktionen definiert sind, auch für Nicht-Klasse - Typen wie statische Arrays. Siehe hier: Wie funktioniert die bereichsbasierte Funktion für einfache Arrays?quelle
begin
undend
ist jedoch ein Einzeiler.auto
auf der anderen Seite wäre ziemlich schwierig.Der richtige Weg, dies zu tun, ist:
Dabei ist T der Typ der Klasse innerhalb des Vektors. Wenn die Klasse beispielsweise CActivity war, schreiben Sie einfach CActivity anstelle von T.
Diese Art von Methode funktioniert auf jeder STL (nicht nur Vektoren, was etwas besser ist).
Wenn Sie weiterhin Indizes verwenden möchten, gehen Sie wie folgt vor:
quelle
std::vector<T>::size_type
immersize_t
? Das ist der Typ, den ich immer dafür benutze.Es gibt einige starke Gründe, Iteratoren zu verwenden, von denen einige hier erwähnt werden:
Ein späterer Containerwechsel macht Ihren Code nicht ungültig.
Wenn Sie also von einem std :: -Vektor zu einer std :: -Liste oder einem std :: -Satz wechseln, können Sie keine numerischen Indizes verwenden, um zu Ihrem enthaltenen Wert zu gelangen. Die Verwendung eines Iterators ist weiterhin gültig.
Laufzeitabfangen ungültiger Iteration
Wenn Sie Ihren Container in der Mitte Ihrer Schleife ändern, wird bei der nächsten Verwendung Ihres Iterators eine ungültige Iteratorausnahme ausgelöst.
quelle
Ich war überrascht, dass niemand erwähnt hat, dass das Durchlaufen eines Arrays mit einem ganzzahligen Index es Ihnen leicht macht, fehlerhaften Code zu schreiben, indem Sie ein Array mit dem falschen Index abonnieren. Wenn Sie beispielsweise verschachtelte Schleifen mit
i
undj
als Indizes haben, können Sie ein Array mitj
und nicht falsch abonniereni
und somit einen Fehler in das Programm einfügen.Im Gegensatz dazu sind die anderen hier aufgeführten Formen, nämlich die bereichsbasierte
for
Schleife und die Iteratoren, viel weniger fehleranfällig. Die Semantik der Sprache und der Typprüfungsmechanismus des Compilers verhindern, dass Sie versehentlich mit dem falschen Index auf ein Array zugreifen.quelle
Mit STL verwenden Programmierer das
iterators
Durchlaufen von Containern, da der Iterator ein abstraktes Konzept ist, das in allen Standardcontainern implementiert ist. Zum Beispielstd::list
hat überhaupt keineoperator []
.quelle
Die Verwendung des Auto-Operators macht die Verwendung wirklich einfach, da Sie sich nicht um den Datentyp und die Größe des Vektors oder einer anderen Datenstruktur kümmern müssen
Iterierender Vektor mit auto und for loop
Ausgabe:
Sie können diese Methode auch verwenden, um Sätze und Listen zu iterieren. Mit Auto erkennt automatisch den Datentyp in der Vorlage verwendet und können Sie es verwenden. Also, auch wenn ich eine hatte
vector
diestring
oderchar
die gleiche Syntax wird gut funktionierenquelle
Die richtige Methode zum Iterieren der Schleife und zum Drucken ihrer Werte lautet wie folgt:
quelle
Hier ist eine einfachere Möglichkeit, Werte im Vektor zu iterieren und zu drucken.
quelle
quelle