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 nochin
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-konstruiertenistreambuf_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 vonstd::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, dassstring
solange befüllt wird, bis der erste mit dem zweitenInputIterator
übereinstimmt. Habe aber auch gerade erst entdeckt, dassstring
einen eigenen Konstruktor nur fürInputIterator
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 zweitenInputIterator
ü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
.