Verständnisfrage istreambuf_iterator



  • std::string get_file_contents(const char *filename)
    {
      std::ifstream in(filename, std::ios::in | std::ios::binary);
      if (in)
      {
        return(std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()));
      }
      throw(errno);
    }
    

    Der Vorteil dieser Methode soll es ja sein, dass der Dateiinhalt nicht irgendwo zwischengespeichert werden muss, sondern direkt in den String kopiert wird, oder?
    Der default-Konstruktor von istreambuf_iterator erzeugt ja ein End-Of-Stream-Objekt (das Objekt beginnt mit der Iteration also beim letzten Zeichen und ist somit direkt fertig iteriert). Woher weiß istreambuf_iterator aber, welcher Stream genutzt werden soll?
    Beim ersten Aufruf wird ja noch in als Stream übergeben. Beim zweiten nicht, wodurch der EOS-Iterator erzeugt wird.

    Bitte um Erklärung 🙂



  • Der istreambuf_iterator<char>(in) weiss ja wenn "sein" Stream "aus" ist (eof). D.h. er weiss selbst dass er zu Ende ist.

    Muss also nur noch der operator == passend implementiert sein, so dass ein "zu Ende gelaufener" istreambuf_iterator mit einem default-konstruierten istreambuf_iterator "equal" vergleicht.



  • Die Iteration beginnt nicht beim letzten Zeichen. Es werden dort zwei istreambuf_iterator erstellt. Der erste kriegt den Stream über den er iterieren soll und stellt den Anfang dar und für den end-of-stream Iterator wird der Default Contructor benutzt. Dann wird der Constructor von std::string benutzt welcher zwei Iteratoren akzeptiert. Dieser inkrementiert dann solange den ersten Iterator bis der end-of-stream Iterator erreicht ist und die ganze Datei eingelesen ist.



  • Achso! Der Default-Konstruktor ist also gar nicht Stream-bezogen sondern nimmt nur so eine Art Standard-Zustand ein, der von jedem istreambuf_iterator angenommen wird, sobald der EOS erreicht ist? Ich konnte nämlich mit der Beschreibung "The default constructor constructs an end-of-stream iterator" von cplusplus.com nicht wirklich was anfangen.
    Wobei ich mir ja hätte denken können, dass string solange befüllt wird, bis der erste mit dem zweiten InputIterator übereinstimmt. Habe aber auch gerade erst entdeckt, dass string einen eigenen Konstruktor nur für InputIterator hat:

    template <class InputIterator>
      string  (InputIterator first, InputIterator last);
    

    Danke!



  • jolo schrieb:

    Wobei ich mir ja hätte denken können, dass string solange befüllt wird, bis der erste mit dem zweiten InputIterator übereinstimmt.

    Achso, ja, sorry, bin davon ausgegengen dass das bekannt ist. Das ist übrigens bei so ziemlich allen Standard-Library Funktionen so die ein Iterator-Paar nehmen.



  • jolo schrieb:

    Der Vorteil dieser Methode soll es ja sein, dass der Dateiinhalt nicht irgendwo zwischengespeichert werden muss, sondern direkt in den String kopiert wird, oder?

    Der wird schon "irgendwo" zwischengespeichert. Wenn du meinst, dass man keinen Puffer bereitstellen muss, dann ja, das ist hier ein Vorteil gegenüber .read .


Log in to reply