Ich suche nach ostream
Operatoren für einige Mathematikklassen (Matrix, Vektor, etc.). Ein Freund hat festgestellt, dass die gcc Standardbibliotheksimplementierung des ostream
Operators für std::complex
die interne Verwendung von enthält ein String-Stream, um die Ausgabe zu formatieren, bevor sie an das tatsächliche ostream
übergeben wird:
Dieses Muster ist auch im Boost sichtbar. Wir versuchen herauszufinden, ob dies ein Muster ist, dem man folgen sollte. Es gab Bedenken, dass ein zusätzlicher Header für den String-Stream eingeschlossen werden muss und dass zusätzliche Heap-Zuweisungen im String-Stream erforderlich sind, die möglicherweise vermieden werden könnten.
Am vernünftigsten wurde vorgeschlagen, dass, wenn der Client diese Funktionalität benötigt, sie den String-Stream erstellen und die Pre-Pass-Funktion selbst übernehmen können.
Kann jemand mir helfen zu verstehen, warum dies als gute Praxis angesehen wird und ob ich es übernehmen sollte?
Überlegen Sie, was passiert, wenn Sie eine Ausgabebreite für den Ostream festlegen und dann einen std :: complex schreiben - Sie möchten nicht, dass sich die Breite nur auf den ersten Ausgabevorgang auswirkt (zB '('
-Zeichen)
Dies sollte "(0,1) "
nicht "( 0,1)"
Wenn Sie die gesamte Ausgabe als einzelne Zeichenfolge formatieren und dann ausschreiben, berücksichtigt die Ausgabe die Feldbreite und andere im Stream festgelegte Formatierungsflags.
Der in einer anderen Antwort angegebene Threading-Grund wird nicht wirklich funktionieren: Die Zeichenfolge kann immer noch auf der Stream-Buffer-Ebene aufgeteilt werden, da diese Operationen nicht atomar sind, wenn sie von mehreren Threads aufgerufen werden.
Allerdings gibt es zwei Überlegungen, die relevant sind:
width()
einer Ausgabe die Anzahl der Zeichen ist, die die gesamte Formatierungszeichenfolge mindestens belegen sollte. Wenn Sie Ausgabeoperatoren intern für einen anderen Ausgabeoperator verwenden, würden Sie das erste Element so einrichten, dass es die Breite einnimmt, und nicht die gesamte resultierende Zeichenfolge, die aus mehreren Komponenten besteht. Bei einer komplexen Zahl würde das reelle Element beispielsweise width()
und nicht die Kombination aus realem Element, Komma und imaginärem Element belegen. Ein Hauptzweck dieses Patterns besteht darin, zu vermeiden, dass die Manipulatoren / Flags des ursprünglichen Streams beibehalten und vor dem Zurücksetzen zurückgesetzt werden. Boost.IoStateSavers beseitigt die Notwendigkeit dafür, also würde ich sagen, dass die Verwendung dieser Bibliothek eine sein würde bessere Praxis.