Why does the constructor and open
method of the std::(i|o)fstream classes take the name of a file as a parameter in the form of a const char*
ins开发者_JAVA百科tead of an std::string
? It seems like the creators of the STL would want to use what they had written instead of using the type they wrote a class to replace.
The string
part of the library was developed after streams, and nobody thought to make the obvious modifications.
It's merely out of political and temporal reality that they never got around to this before shipping C++98, and nobody bothered bringing it up again because you could always solve it with .c_str()
.
C++0x fixes this (see 27.9.1.6).
Welcome to C++.
It's mainly for historical reasons, as far as I know. ifstream
and ofstream
existed long before std::string
. They didn't even have a std::
back then.
Class std::string
implements the concept of "run-time-sized resizable string". This is when this class should be used - when you need a string whose size is only known at run-time and which is run-time resizable as well. In situations when you don't need these features using std::string
is an overkill. Apparently, the authors of the library didn't think that they needed a run-time resizable string to represent a file name, so they opted for a minimalistic solution: they used a C-string where a C-string was sufficient. This is actually a very good principle for designing library interfaces: never require something that you don't really need.
It is true that these days we often see people who encourage C++ programmers to use std::string
whenever they need a string, any string. They often claim that classic C strings should be reserved to C code. In general case this is a bogus philosophy. Gratuitous use of comparatively heavy objects like std::string
is more appropriate in languages like Java, but is normally unacceptable in C++.
Yes, it is possible to get away with using std::string
all the time in some C++ applications ("it is possible to write a Java program in C++"), but in such a generic low-level library as C++ standard library forcing the user to use std::string
without a good reason (i.e. imposing unnecessary requirements) would not look good.
My bet is that the iostream
hierarchy / library (including (i|o)fstream
) was invented / developed apart from std::string
, and they only first met when put together in the std
library.
At the time of invention of iostream
, there were maybe many different string
implementations going around and to support maximum portability, they decided to bet on a data type that's always available, and that's a simple char const*
c-style string.
Just looking through my G++'s <fstream>
header, I noticed that all of the references to std::basic_string
or any of its typedefs
are in sections delimited with #ifdef __GXX_EXPERIMENTAL_CXX0X__
.
This suggests to me that the iostreams library was designed to be independent of the string library, so that if you didn't use std::string
, you didn't have to pay for it (this has historically been a very important design principle in C++). This would also explain why getline(std::istream&, std::string&)
is a free function defined in <string>
, rather than a member function like istream::getline(char*, streamsize)
.
This also suggests to me in the C++0x standardization viewed this as a design flaw, and decided that the inconvenience of making the iostreams library independent of the string library just wasn't worth it.
(I can't be bothered to go find a working draft of the C++0x spec, or systematically check all of the iostreams related headers to confirm any of this.)
精彩评论