c++ write Warum nehmen die std:: fstream-Klassen keine std:: string?




stringstream (8)

Dies ist keine Designfrage, wirklich, obwohl es so aussieht. (Nun, okay, es ist eine Designfrage). Was ich frage mich ist, warum die C ++ std::fstream Klassen nicht eine std::string in ihrem Konstruktor oder offenen Methoden nehmen. Jeder liebt Codebeispiele so:

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string filename = "testfile";      
    std::ifstream fin;

    fin.open(filename.c_str()); // Works just fine.
    fin.close();

    //fin.open(filename); // Error: no such method.
    //fin.close();
}

Das bringt mir die ganze Zeit beim Arbeiten mit Dateien. Sicher würde die C ++ Bibliothek wo immer möglich std::string ?


Vielleicht ist es ein Trost: Alle Stream's haben eine offene (String const &, ...) neben dem offenen (char const *, ...) im Arbeitsentwurf des C ++ 0x-Standards bekommen. (siehe zB 27.8.1.6 für die basic_ifstream-Deklaration)

Wenn es fertiggestellt und implementiert wird, wird es dich nicht mehr bringen :)


C ++ wuchs auf kleineren Maschinen auf als die Monster, für die wir heute Code schreiben. Damals, als Iostream neu war, haben sich viele Entwickler wirklich um die Code-Größe gekümmert (sie mussten ihr gesamtes Programm und ihre Daten in mehrere hundert KB einpassen). Daher wollten viele die "große" C ++ - String-Bibliothek nicht verwenden. Viele haben die Iostream-Bibliothek nicht einmal aus den gleichen Gründen, der Code-Größe, benutzt.

Wir hatten nicht Tausende von Megabyte RAM, um herumzuwerfen, wie wir es heute tun. Wir hatten normalerweise keine Funktionsebenenverknüpfung, so dass wir dem Entwickler der Bibliothek ausgeliefert waren, um viele separate Objektdateien zu verwenden oder Tonnen von nicht aufgerufenem Code zu verwenden. All diese FUD haben Entwickler dazu gebracht, sich von std :: string abzuwenden.

Damals habe ich auch std :: string vermieden. "Zu aufgebläht", "zu oft Malloc genannt" usw., indem man Stack-basierte Puffer für Strings täuschend verwendet und dann alle Arten von lästigem Code hinzufügt, um sicherzustellen, dass es nicht überläuft.


Es gibt mehrere Stellen, an denen das C ++ - Standardkomitee die Interaktion zwischen Einrichtungen in der Standardbibliothek nicht wirklich optimiert hat.

std::string und seine Verwendung in der Bibliothek ist eine davon.

Ein anderes Beispiel ist std::swap . Viele Container haben eine Swap-Member-Funktion, es wird jedoch keine Überladung von std :: swap geliefert. Das gleiche gilt für std::sort .

Ich hoffe, all diese kleinen Dinge werden im kommenden Standard behoben sein.


Es ist belanglos, das ist wahr. Was meinst du damit, dass die Schnittstelle von std :: string groß ist? Was bedeutet groß in diesem Zusammenhang - viele Methodenaufrufe? Ich bin nicht witzig, ich bin wirklich interessiert.

Es hat mehr Methoden, als es wirklich benötigt, und sein Verhalten bei der Verwendung von Integral-Offsets anstelle von Iteratoren ist ein bisschen zweifelhaft (wie es im Gegensatz zu dem Rest der Bibliothek steht).

Das wirkliche Problem, das ich denke, ist, dass die C ++ Bibliothek drei Teile hat; Es hat die alte C-Bibliothek, es hat die STL, und es hat Strings-und-Iostreams. Obwohl einige Anstrengungen unternommen wurden, um die verschiedenen Teile zu überbrücken (z. B. das Hinzufügen von Überladungen zur C-Bibliothek, weil C ++ das Überladen unterstützt; das Hinzufügen von Iteratoren zu basic_string; das Hinzufügen der Iostream-Iteratoradapter), gibt es viele Inkonsistenzen bei Ihnen schau dir das Detail an.

Zum Beispiel enthält basic_string Methoden, die unnötige Duplikate von Standardalgorithmen sind; Die verschiedenen Suchmethoden könnten wahrscheinlich sicher entfernt werden. Ein anderes Beispiel: Locales verwenden rohe Zeiger anstelle von Iteratoren.


Ich glaube, dass darüber nachgedacht wurde und getan wurde, um die Abhängigkeit zu vermeiden; Dh #include <fstream> sollte nicht zu #include <string> zwingen.

Um ehrlich zu sein, scheint dies eine ziemlich belanglose Angelegenheit zu sein. Eine bessere Frage wäre, warum ist die Schnittstelle von std :: string so groß?


Durch die Verwendung einer C-Zeichenfolge reduzierte die Klasse C ++ 03 std::fstream die Abhängigkeit von der Klasse std::string . In C ++ 11 jedoch std::fstream Klasse std::fstream die Übergabe einer std::string für ihren Konstruktorparameter.

Nun können Sie sich wundern, warum es keine transparente Umwandlung von einer std:string in eine C string gibt, so dass eine Klasse, die eine C-Zeichenfolge erwartet, immer noch eine std::string wie eine Klasse, die eine std::string erwartet kann eine C-Zeichenfolge nehmen.

Der Grund ist, dass dies einen Umwandlungszyklus verursachen würde, was wiederum zu Problemen führen könnte. Angenommen, std::string wäre in eine C-Zeichenfolge konvertierbar, sodass Sie std::string s mit fstream s verwenden fstream . Angenommen, die C-Zeichenfolge ist in std::string s konvertierbar, ebenso wie der Status im aktuellen Standard. Betrachten Sie nun Folgendes:

void f(std::string str1, std::string str2);
void f(char* cstr1, char* cstr2);

void g()
{
    char* cstr = "abc";
    std::string str = "def";
    f(cstr, str);  // ERROR:  ambiguous
}

Da Sie beide Wege zwischen einer std::string und einer C string konvertieren können, könnte der Aufruf von f() in eine der beiden f() Alternativen aufgelöst werden und ist daher nicht eindeutig. Die Lösung besteht darin, den Konvertierungszyklus zu c_str() indem eine Konvertierungsrichtung explizit gemacht wird, was die STL mit c_str() .


Heutzutage können Sie dieses Problem sehr leicht lösen: fügen Sie -std=c++11 zu Ihren CFLAGS .


@ Bernard:
Monolithen "Ungespannt" "Alle für einen, und einer für alle" mag für Musketiere funktionieren, aber es funktioniert nicht annähernd so gut für Klassenkünstler. Hier ist ein Beispiel, das nicht ganz beispielhaft ist, und es zeigt, wie sehr man schief gehen kann, wenn Design zu Überdesign wird. Das Beispiel stammt leider aus einer Standardbibliothek in Ihrer Nähe ... ~ http://www.gotw.ca/gotw/084.htm





stdstring