it-swarm.com.de

Was ist ein Iterator im Allgemeinen?

Dieses Problem tritt auf, wenn ich versucht habe, eine C++ - Klassenvorlage mit ctor zu schreiben, die "general iterator" akzeptiert. Ich weiß nicht, ob es angebracht ist, das Wort general hier zu verwenden, aber ich meine, dass es Iteratoren genauso wie STL-Container akzeptieren kann. 

In anderen Worten, ich bin verwirrt über Iterator . Es scheint, dass alle STL-Container den gleichen Typ-Iterator haben. Was also ist dieser Typ? Ist es nur ein Zeiger? Oder etwas komplizierter? STL-Container akzeptieren jedoch normale Zeiger.

(Ich möchte es mit Iterator<T> in Java vergleichen, was ziemlich einfach ist und nur eine Klasse ist.)

28
Ziqi Liu

In C++ ist ein Iterator ein Konzept, kein konkreter (oder abstrakter) Typ, sondern ein any -Typ, der bestimmten iterator like -Regeln folgt.

Zum Beispiel können Iteratoren allgemein ++i inkrementiert werden. Sie können auf (dereferenziert) *i zugreifen, um den Wert zu erhalten, auf den sie aktuell zeigen. Sie sind im Wesentlichen Abstraktionen eines pointer.

In den Containern und Algorithmen der Standard Library gibt es verschiedene Arten von Iteratoren mit unterschiedlichen Eigenschaften. Ihre Eigenschaften sind hier aufgelistet:

https://de.cppreference.com/w/cpp/iterator

Wenn Sie in C++ Algorithmen schreiben, die Iteratoren akzeptieren, akzeptieren Sie im Allgemeinen nur generic template-Parameter und verwenden Sie die entsprechenden Iteratoreigenschaften in der Funktion. Der Compiler beschwert sich, wenn der Benutzer Ihrer Funktion etwas übergibt, das den Iteratorregeln nicht entspricht:

template<typename Iterator>
void my_algorithm(Iterator begin, Iterator end)
{
    for(; begin != end; ++begin)
        std::cout << *begin << '\n';
}

Sie können eine ganze Reihe spezifischer Überprüfungen hinzufügen, um sicherzustellen, dass der Benutzer etwas Vernünftiges bestanden hat. Dies ist jedoch zu umfangreich für diese Frage.

Hinweis:

Während derzeit Konzepte, wie zum Beispiel Iterator , nur eine Reihe von vereinbarten semantischen Eigenschaften im Standard sind, die Programmierer befolgen müssen, eine umfassendere Lösung, die formalisieren so Konzepte (im Code) ist für die nächste Version des Standards vorgesehen, C++ 20 .

37
Galik

Iteratoren als Konzept stammen, bevor C++ ein Standard war.

C++ begann als C mit Klassen. Weitere Funktionen wurden hinzugefügt, und eine exponentiell wachsende Anzahl von Leuten hat sich für die Sprache interessiert.

Eine sehr wichtige Arbeit wurde als STL bezeichnet - die Standard Template Library - ursprünglich von Stepanov und Lee geschrieben. 1994 bei Hewlett-Packard, später von SGI gepflegt.

Diese Bibliothek verwendete den Template-Metaprogrammierungs-Teil von C++ auf recht revolutionäre Weise. Es wurde geschrieben, um nahezu unbegrenzte Performance mit abstrahierten Typen zu ermöglichen, wobei Algorithmusimplementierungen von Containerimplementierungen für nahezu beliebige Typen getrennt sind.

Iteratoren sind ein Konzept - ein höherer Typ

Der Iterator war ein -Konzept. Ein Konzept in C++ ist eine Kategorie von Typen (ein Typ, den Sie sagen könnten). Konzepte in C++ werden nicht vom Compiler (zu diesem Zeitpunkt) durchgesetzt.

Ein Typ erfüllt ein Konzept, wenn er über die erforderlichen Operationen verfügt, und diese Operationen halten die Regeln des Konzepts ein.

In der STL und später im C++ - Standard gibt es eine Konzepterie um Iteratoren. Sie gehen vom am wenigsten einschränkenden (einem Iterator) zum größten (einem zusammenhängenden Iterator mit Schreibzugriff mit wahlfreiem Zugriff) und bilden einen Baum.

Template-Funktionen schreiben Funktionen

Wenn ein Vorlagenalgorithmus nach einem Iterator fragt, fragt er nach einem Typ, der das Iterator-Konzept erfüllt (wie im C++ - Standard beschrieben). Wenn sie nach einem RandomAccessIterator fragen, fragen sie nach einem Typ, der das RandomAccessIterator-Konzept zufriedenstellt (dazu gehören auch das Iterator-Konzept, das ForwardIterator-Konzept und einige andere).

template<class ForwardIterator> void std::sort( ForwardIterator, ForwardIterator ) ist also eine Template-Funktion, die zwei Instanzen desselben Typs verwendet, die das ForwardIterator-Konzept erfüllen.

ForwardIterators müssen eine Reihe von Operationen unterstützen (*it, ++it, bool b = it != it, bool b = it == it usw.), bestimmte Merkmale unterstützen (iterator_traits<it>::iterator_category, iterator_traits<it>::reference, iterator_traits<it>::value_type usw.), und diese Operationen müssen bestimmten Regeln folgen.

Wenn Sie einen Typ zuführen, der RandomAccessIterator entspricht, garantiert std::sort eine bessere Leistung als bei einer ForwardIterator.

Ein unaufbereiteter Zeiger erfüllt den Forward-RandomAccess-Iterator, ohne dass Sie etwas tun müssen. std::vector<?>::iterator genügt auch für beides, ist aber oft kein reiner Zeiger (die std-Bibliothek hat etwas gearbeitet).

Die zwei Typen - der unformatierte Zeiger und std::vector<?>::iterator - sind normalerweise nicht miteinander verwandt. Das Vorlagen- und Merkmalssystem von C++ ermöglicht, dass nicht verwandte Typen von demselben Vorlagenalgorithmus mit einem Laufzeitaufwand von null verstanden werden.

In c ++ 2a gibt es Pläne, In-Language-Konzepte einzuführen, die einige der Anforderungen für Dinge wie RandomAccessIterator prüfen und die anderen Anforderungen dokumentieren, die praktisch nicht überprüft werden können.

C++ ist keine OO-Sprache

Sie sind möglicherweise verwirrt, wenn Sie sich an objektorientierte Sprachen gewöhnen. C++ unterstützt die objektorientierte Programmierung, ist jedoch keine objektorientierte Sprache. Es unterstützt Polymorphismus - mehrere Typen werden gleich behandelt - ohne objektbasierte Vererbung auf verschiedene Arten.

In einer objektorientierten Sprache erbt jeder Iterator von einem abstrakten Iteratortyp. Die Algorithmen würden über diese abstrakte Schnittstelle mit dem Iterator interagieren und häufig Aufrufe über eine virtuelle Funktionstabelle ableiten. Werte des Typs wären nicht möglich, da der Algorithmuscode kompiliert würde, ohne zu wissen, wie viele Bytes die Iteratoren beanspruchen, so dass eine zusätzliche Umleitung auftreten würde.

In C++ ist der Algorithmus erst dann eine Funktion, wenn Sie den Typ des Iterators übergeben. Zu diesem Zeitpunkt ist die Funktion für diesen Iterator benutzerdefiniert. Der C++ - Standard besagt, dass die Funktion, die von der Vorlage geschrieben wird, ein bestimmtes Verhalten hat, wenn der Iterator bestimmte Vorgänge ausführt (das Konzept muss eingehalten werden).

Diese mit der Vorlage geschriebene Funktion weiß, wie groß der Iterator ist, was die Vorgänge bewirken, die Operationen inlinieren und Instanzen des Iterators in Puffern oder auf dem Stack als Wert speichern können. Wenn der Iterator dies nicht erzwingt, gibt es keinen virtuellen Versand. Wenn die Operationen sichtbar sind, können sie in die geschriebene Funktion eingebettet werden.

Enge Schleifen können vom Compiler untersucht werden und es kann zu Vektorisierung kommen, als ob Sie die Funktion von Hand geschrieben hätten.

Dieselbe Vorlage kann Datenbankeinträge oder Zeichenfolgen oder Ganzzahlen sortieren. In jedem Fall wird eine neue Funktion geschrieben, und der Compiler soll versuchen, diese schneller zu machen.

TL; DR

Iteratoren sind kein Typ; Sie sind eine Art Typ. Vollständig nicht verwandte Typen können beide Iteratoren sein. Es gibt keine Basisklasse für Iteratoren. Es gibt nur bestimmte Wege, auf die sie garantieren, dass sie sich verhalten.

C++ - Algorithmen generieren benutzerdefinierten Code für jeden Iteratortyp, den Sie an std::sort übergeben. Wenn Sie einen Vektor aus int und einen Vektor aus Zeichenketten sortieren, wird kein Binärcode zwischen den beiden geteilt (mit Ausnahme der Möglichkeit der Komdat-Faltung).Die Konzepte (Art des Typs) Iterator/ForwardIterator/RandomAccessIterator sind dokumentierte Anforderungen an die Typen, die an die C++ - Algorithmen übergeben werden. Es wird keine Durchsetzung durchgeführt, es sei denn, der Compiler kann buchstäblich alles tun, wenn Sie die Anforderungen nicht erfüllen.

The concepts (kind of type) Iterator/ForwardIterator/RandomAccessIterator are documented requirements on the types passed to the C++ algorithms. No enforcing is done, other than that the compiler is free to do literally anything if you fail to meet the requirements.

Iterator ist ein Verhaltensmuster, das als Teil von "Gang of Four Design Patterns" beschrieben wird. Es löst ein Problem, wenn Objekte in einem Aggregatobjekt durchlaufen werden, ohne die interne Struktur dieses Objekts zu kennen.

Weitere Informationen zum Iteratormuster finden Sie unten: http://www.blackwasp.co.uk/Iterator.aspx

0
sshah