Wird ein veränderbarer Eingabe-Iterator inkrementiert, werden alte Iterator-Werte ungültig?

8
  

Iteratoren, die die Anforderungen von Ausgabe-Iteratoren weiter erfüllen, werden veränderbare Iteratoren genannt. Nicht veränderbare Iteratoren werden als konstante Iteratoren bezeichnet. [24.2.1: 4]

Dies deutet darauf hin, dass Sie einen änderbaren Eingabe-Iterator haben könnten, der die Anforderungen von Eingabe- und Ausgabe-Iteratoren erfüllt.

Nach dem Inkrementieren eines Eingabe-Iterators müssen Kopien seines alten Werts nicht dereferenziert werden [24.2.3]. Der Standard sagt jedoch nicht dasselbe für Ausgabe-Iteratoren; Tatsächlich wird die operationale Semantik für das Postfix-Inkrement als { X tmp = r; ++r; return tmp; } angegeben, was darauf hindeutet, dass die Ausgabe-Iteratoren möglicherweise keine alten Iterator-Werte ungültig machen (Kopien davon).

Kann also ein veränderbarer Eingabe-Iterator alte Iterator-Kopien ungültig machen?

Wenn ja, wie würden Sie Code wie X a(r++); *a = t oder X::reference p(*r++); p = t mit (z. B.) einem Proxy-Objekt unterstützen?

Wenn nicht, warum behauptet boost::iterator , dass es eine a benötigt Proxy-Objekt? (Link ist Code; scrollen Sie nach unten, um die Kommentare zu struct s writable_postfix_increment_proxy und postfix_increment_result ) zu lesen. Das heißt, wenn Sie eine (dereferenzierbare) Kopie des alten Iteratorwerts zurückgeben können, warum sollten Sie diese Kopie in einen Proxy einbinden?

    
nknight 13.08.2012, 06:15
quelle

2 Antworten

6

Die Erklärung findet sich im nächsten Abschnitt, [24.2.5] Vorwärts-Iteratoren, wo angegeben wird, wie diese sich von Eingabe- und Ausgabe-Iteratoren unterscheiden:

  

Zwei dereferenzierbare Iteratoren a und b des Typs X bieten die Mehrfachpass-Garantie wenn:

     

- a == b bedeutet ++a == ++b und
  - X ist ein Zeigertyp oder der Ausdruck (void)++X(a), *a entspricht dem Ausdruck *a .

     

[Hinweis: Die Anforderung, dass a == b impliziert ++a == ++b (was nicht für Eingabe- und Ausgabe-Iteratoren gilt) und das Entfernen der Beschränkungen für die Anzahl der Zuweisungen durch einen veränderbaren Iterator (was für Ausgabe-Iteratoren gilt) ermöglicht die Verwendung von mehrwegigen eindirektionalen Algorithmen mit Vorwärts-Iteratoren.   -Hinweis]

Leider muss der Standard als Ganzes gelesen werden, und die Erklärung ist nicht immer dort, wo Sie es erwarten.

    
Bo Persson 13.08.2012, 06:41
quelle
4

Ein- und Ausgabe-Iteratoren sind grundsätzlich so konzipiert, dass sie Single-Pass-Traversierungen ermöglichen: Sequenzen beschreiben, bei denen jedes Element nur einmal besucht werden kann.

Streams sind ein großartiges Beispiel. Wenn Sie von stdin oder einem Socket lesen oder in eine Datei schreiben, dann gibt es nur die aktuelle Position des Streams. Alle anderen Iteratoren, die auf dieselbe zugrunde liegende Sequenz verweisen, werden ungültig, wenn Sie einen Iterator inkrementieren.

Vorwärts-Iteratoren ermöglichen Multi-Pass-Traversal, die zusätzliche Garantie, die Sie benötigen: Sie stellen sicher, dass Sie Ihren Iterator kopieren, das Original inkrementieren können, und die Kopie immer noch auf die alte Position zeigt, also Sie kann von dort iterieren.

    
jalf 13.08.2012 08:14
quelle

Tags und Links