Why does (i|o)fstream take a const char* parameter

2019-01-12 02:53发布

问题:

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* instead 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.

回答1:

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.



回答2:

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++.



回答3:

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.



回答4:

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.



回答5:

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.)



标签: c++ stl history