istream_iterator



  • Hallo liebes Forum,
    kann mir jemand folgenden Code Schritt für Schritt erklären:

    cout << "Eingabe: ";
    istream_iterator<int> von(cin), bis;
    
    cout << "Vector... ";
    vector<int> v(von, bis);
    

    Eingabe: 5
    Vector... 6
    7
    9
    10
    x

    Ich weiss nicht was mit welcher Reihenfolgen passiert. Wo befindet sich das Programm nach der ersten Eingabe.

    1. "Eingabe: " wird ausgegeben
    2. cin wird durch Konstruktor von istream_iterator "von" geöffnet, es wird gewartet bis Benutzer was eingibt
    3. "Vector... " wird ausgegeben, und wo ist das Programm jetzt, ist der vector "v" schon erstellt worden?

    Ich verstehe nämlich nicht ganz warum ich immer wieder Zahlen eingeben kann, es hört nur auf wenn cin keinen Wert von Typ int liefert (hier weiss ich auch warum, unten beim Zitat).

    Unklar ist mir warum man immer wieder etwas in cin schreiben kann und wie der Kopierkonstruktor von vector v vorgeht, da der istream_iterator nach der Eingabe von einem Buchstaben ja einen Fehlerstatus hat, also wieder ein Defaultkonstrukt wird.

    http://www.cplusplus.com/reference/iterator/istream_iterator/

    This kind of iterator has a special state as an end-of-stream iterator, which is acquired if an input operations fails (as returned by fail after an operation with the associated stream), and is also the resulting value of a default-constructed object.


  • Mod

    Zeile 1: "Eingabe: " wird nach stdout geschrieben. Die Ausgabe wird nicht zwangsläufig geflusht.
    Zeile 2: Der Iterator von wird mit dem Argument cin konstruiert. Ein istream_iterator darf (muss aber nicht) bereits versuchen, ein Element aus dem Stream zu extrahieren. Wenn er das tut, wird der an den Stream ge-tie-ete Stream geflusht. Bei dir wird anscheinen versuchst, ein Element zu extrahieren. Da cin und cout gegenseitig ge-tie-et sind, ist hier auch garantiert, dass cout nun geflusht wurde.
    Danach wird noch der End-of-Stream Iterator bis konstruiert, nichts besonderes passiert.
    Zeile 3: "Vector... " wird nach stdout geschrieben. Wieder ohne flush.
    Zeile 4: Der vector-Konstruktor wird so oft den ersten Iterator dereferenzieren und inkrementieren, bis dieser mit dem zweiten erfolgreich auf Gleichheit geprüft wird. Bei jedem Inkrement von von wird ein neuer Wert aus dem Stream extrahiert. Wenn bei der Konstruktion in Zeile 2 noch kein Wert extrahiert wurde, so geschieht dies beim ersten Dereferenzieren.
    Wenn eine Extraktion scheitert, so wird der Iterator auf den End-of-Stream Sonderwert gesetzt.

    Unklar ist mir warum man immer wieder etwas in cin schreiben kann und wie der Kopierkonstruktor von vector v vorgeht, da der istream_iterator nach der Eingabe von einem Buchstaben ja einen Fehlerstatus hat, also wieder ein Defaultkonstrukt wird.

    Ich verstehe nicht, was dir da dran unklar ist. cin ist keine "lies etwas von der Tastatur ein"-Funktion. cin ist ein Objekt von Typ istream. Ein abstraktes Gebilde, das auf Zeichenströmen arbeitet und Extraktionsfunktionen anbietet, die diese Zeichenströme als Zahlen oder andere Objekte interpretieren können. Der "lies von der Tastatur"-Teil deines Computers sitzt ganz woanders und kümmert sich nicht, was dein Programm macht. Der Teil von cin, der sich um den Zeichenstrom kümmert (der streambuf), kümmert sich auch nicht um irgendwelche Teile der höheren Programmlogik.



  • Der vector-Konstruktor wird so oft den ersten Iterator dereferenzieren und inkrementieren, bis dieser mit dem zweiten erfolgreich auf Gleichheit geprüft wird.

    Ah, klar. Ich hatte da einen Denkfehler. Jetzt ergibt alles wieder einen Sinn. Ich fragte mich andauernd, wo hier der Iterator inkrementiert wird, ist aber ganz logisch, dass der Kopierkonstrktor des Vectors dies macht xD

    Danke



  • Das ist nicht der Kopierkonstruktor. Laut Referenz[1] nennt man das Ding Range-Constructor. Und der könnte etwa so aussehen:

    template <class InputIterator>
    vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type())
     : vector(alloc) // Delegating Constructor
    {
    	for( ; first != last; ++first)
    		this->push_back(*first);
    }
    

    Betonung liegt auf könnte.

    Wie ich grad beim MSVC sehe, ruft der Constructor insert auf, das ruft verschiedene weitere interne inserts auf und da wird dann irgendwann gepush-backt.

    Nichts desto trotz kopiert der vector die Element in sich rein.

    [1]


Anmelden zum Antworten