2012-05-12 10 views

Antwort

35

IO-Streams verwenden streambufs als Quelle/Ziel der Eingabe/Ausgabe. Effektiv erledigt die streambuf-Familie die gesamte Arbeit in Bezug auf IO und die IOstream-Familie wird nur für die Formatierung und für die String-/from-string-Transformation verwendet. Jetzt

, nimmt istream_iterator eine Vorlage Argument, das sagt, was der unformatierte String-Sequenz aus dem streambuf sollte so formatiert werden, wie istream_iterator<int> interpretieren wird (durch Leerzeichen getrennt) alle eingehenden Text als int s.

Auf der anderen Seite kümmert sich istreambuf_iterator nur um die rohen Zeichen und iteriert direkt über die zugehörige streambuf der istream, dass es übergeben wird.

Im Allgemeinen, wenn Sie nur an den rohen Zeichen interessiert sind, verwenden Sie eine istreambuf_iterator. Wenn Sie an der formatierten Eingabe interessiert sind, verwenden Sie istream_iterator.

Alles, was ich sagte, gilt auch für ostream_iterator und ostreambuf_iterator.

+0

"Wenn Sie nur an den rohen Charakteren interessiert sind, verwenden Sie einen istream_iterator" - sollte das "istreambuf_iterator" sein? – Mankarse

+0

@Mankarse: Ähm, natürlich danke. – Xeo

+0

Dadurch wurde es für mich viel klarer, danke! – dextrey

7

Hier ist ein wirklich schlecht gehütetes Geheimnis: ein Iostream per se, hat fast nichts mit dem tatsächlichen Lesen oder Schreiben von/zu einer Datei auf Ihrem Computer zu tun.

Ein Iostream im Grunde als „Heiratsvermittler“ wirkt zwischen einem streambuf und einem locale:

enter image description here

Die Iostream speichern einigen Zustand über, wie Conversions sollte (zB die aktuelle Breite und Genauigkeit für ein getan werden Umwandlung). Es verwendet diese, um das Gebietsschema zu steuern, wie und wo eine Umwandlung durchzuführen ist (z. B. wandle diese Zahl in eine Zeichenkette in diesem Puffer mit der Breite 8 und der Genauigkeit 5 um).

Obwohl Sie nicht direkt danach gefragt haben, ist das Gebietsschema seinerseits wirklich nur ein Container - aber (für eher eine Kuriosität) ein typensicherer heterogener Container. Die Dinge, die es enthält, sind facet s. Ein Facettenobjekt definiert eine einzelne Facette eines allgemeinen Gebietsschemas. Der Standard definiert eine Reihe von Facetten für alles von Lesen und Schreiben von Zahlen (num_get, num_put) bis zur Klassifizierung von Zeichen (die ctype Facette).

Standardmäßig verwendet ein Stream das Gebietsschema "C". Das ist ziemlich einfach - Zahlen werden nur als ein Strom von Ziffern konvertiert, die einzigen Dinge, die sie als Buchstaben erkennt, sind die 26 Kleinbuchstaben und 26 Großbuchstaben in Englisch und so weiter. Sie können jedoch imbue einen Stream mit einem anderen Gebietsschema Ihrer Wahl senden. Sie können Gebietsschemas auswählen, die von in Strings angegebenen Namen verwendet werden. Besonders interessant ist eine, die durch eine leere Zeichenfolge ausgewählt wird. Die Verwendung einer leeren Zeichenfolge weist die Laufzeitbibliothek im Wesentlichen an, das Gebietsschema auszuwählen, von dem sie "denkt", dass es am besten geeignet ist, in der Regel basierend darauf, wie der Benutzer das Betriebssystem konfiguriert hat. Dadurch kann Code Daten in einem lokalisierten Format verarbeiten, ohne für ein bestimmtes Gebietsschema explizit geschrieben zu werden.

der grundlegende Unterschied zwischen einem istream_iterator So, und ein istreambuf_iterator ist, dass die Daten aus einem istreambuf_iterator kommt nicht durch (die meisten der) Transformationen durch das Gebietsschema getan gegangen ist, aber Daten aus einer istream_iterator kommenden umgewandelt worden nach dem Gebietsschema.

Für das, was es wert ist, dass „die meisten“ im vorigen Absatz wird auf die Tatsache, dass, wenn Sie Daten von einem istreambuf lesen (über einen Iterator oder aus anderen Gründen) ein wenig locale-basierte Transformation ist erledigt: zusammen mit verschiedenen "Formatierung" Arten von Dingen, das Gebietsschema enthält eine Codecvt-Facette, die verwendet wird, um von einigen externen Darstellung zu einigen internen Darstellung (z. B. UTF-8 zu UTF-32) zu konvertieren.

Es kann mehr Sinn machen, die Tatsache zu ignorieren, dass sie in einem locale beide gespeichert sind, und denkt nur an den einzelnen Facetten beteiligt: ​​

enter image description here

Also das ist der wirkliche Unterschied zwischen einem istream_iterator und ein istreambuf_iterator. Ein wenig Transformation wird (zumindest potentiell) an den Daten von beiden vorgenommen, aber im Wesentlichen erfolgt weniger für die Daten, die von einem istreambuf_iterator stammen.

+0

Gute Erklärung. Was ist mit der Verwendung von Streambufs direkt für rohe Binärdaten, ist das möglich? – Pavel

+0

@Pavel: So funktionieren die C++ - Iostreams nicht, aber zumindest theoretisch gibt es keinen Grund, warum sie das nicht könnten. Ich bezweifle aber, dass Sie das möchten - wenn Sie das täten, müssten Sie die 'codecvt'-Konvertierung jeweils ein Zeichen nach dem anderen anwenden, während Sie die Daten aus dem Rohpuffer lesen, von dem ich glaube, dass er normalerweise einen fairen Wert verliert Menge an Geschwindigkeit (verglichen mit der Umwandlung eines ganzen Puffers gleichzeitig). –

+0

Das ist der Grund, warum ich Iostreams nicht verwenden möchte, da ich nicht möchte, dass Codecvt beteiligt ist. – Pavel