为什么(i|o)fstream需要使用const char*参数作为文件名?

16
为什么 std::(i|o)fstream 类的构造函数和 open 方法接受一个以 const char* 形式表示文件名的参数,而不是使用 std::string 呢?似乎 STL 的创建者会想要使用他们所编写的内容来替换使用其所写类的类型。

2
添加了 history 标签,因为我相信它背后一定有历史原因。 - Xeo
2
请注意,在C++0x中,文件流现在具有构造函数重载,可以使用std::string const&,因此本讨论纯粹是历史性的。 - ildjarn
@ildjarn:好知道,我还没有看过C++0x的std库。 :) - Xeo
1
+1 真的很喜欢阅读这个问题的所有答案和评论。一开始看起来很简单! - idz
5个回答

13

这个库中的string部分是在流之后开发的,没人想到要做明显的修改。

仅仅是由于政治和时间上的现实,他们在发布C++98之前没有能够处理这个问题,而且因为你总是可以用.c_str()来解决它,所以也没有人再次提起。

C++0x修复了这个问题(参见27.9.1.6)。

欢迎使用C++。


那时没有人想到这个想法是完全错误的。相反,这在90年代和以后广泛讨论过。只是当时没有人提出一个能够改变足够多有投票权的标准化委员会成员意见的提案。当时最突出的反对意见可能是流应该可以在没有<string>的情况下使用。我当时不同意,现在仍然不同意,但我必须承认这个论点有一些优点。 - sbi
@sbi:在答案中将“nobody”替换为“委员会无投票成员”。 - Lightness Races in Orbit

6

据我所知,这主要是出于历史原因。在std::string存在之前,ifstreamofstream就已经存在了。当时它们甚至还没有std::


如果这是真的,那么这就是答案。然而,将参数从const char*更改为std::string不会破坏现有的代码,因为通过stringconst char*构造函数,它们之间存在隐式转换(除非我误解了什么,这总是可能的)。为什么他们没有改变它呢? - Seth Carnegie
1
@Sethпјҡж”№еҸҳеҸӮ数并йҡҗејҸдҪҝз”Ёstd::stringжһ„йҖ еҮҪж•°дјҡз ҙеқҸе·Із»Ҹзј–иҜ‘зҡ„д»Јз Ғзҡ„дәҢиҝӣеҲ¶е…је®№жҖ§гҖӮеҸҰдёҖж–№йқўпјҢж·»еҠ дёҖдёӘйҮҚиҪҪжҳҜе®Ңе…ЁеҸҜд»Ҙзҡ„пјҢ并且已з»ҸеңЁC++0xж ҮеҮҶдёӯе®һзҺ°дәҶгҖӮ - Ken Bloom
@Ken,感谢您的解释。虽然我仍然认为匿名的负评对推动讨论没有什么帮助。 - idz
@idz:这不是一个真正的讨论网站,我们需要推动讨论。人们发布答案。人们投票。最佳答案获胜。 - Ken Bloom
@Seth:不一定;实现完全可以在其运行时内定义_标准库_符号,并静态链接该运行时。无论它是否这样做,您仍然必须考虑链接在一起的两个目标文件之间的兼容性。 - Lightness Races in Orbit
显示剩余6条评论

4

std::string实现了“运行时大小可调整的字符串”概念。当您需要一个仅在运行时才知道大小且可以在运行时调整大小的字符串时,应使用此类。在不需要这些功能的情况下,使用std::string会过度。显然,库的作者认为他们不需要一个运行时可调整大小的字符串来表示文件名,因此他们选择了一种简约的解决方案:在C字符串足够的情况下使用C字符串。这实际上是设计库接口的一个非常好的原则:永远不要要求您实际上不需要的东西。

确实,现在我们经常看到人们鼓励C++程序员在需要任何字符串时都使用std::string。他们经常声称经典的C字符串应该保留给C代码。在一般情况下,这是一种虚假的哲学。在像Java这样的语言中,比较重的对象(如std::string)的不必要使用更为合适,但在C ++中通常是不可接受的。

是的,在某些C++应用程序中始终使用std::string是可能的(“可以在C++中编写Java程序”),但在像C ++标准库这样的通用低级库中,强制用户在没有充分理由的情况下使用std::string(即强加不必要的要求)看起来不好。


9
胡说八道。实际上没有任何实际原因不这样做;只是政治和时间表妨碍了在C++98发布之前将std::string应用于STL继承的流特性,他们从未费心更新它。我不确定C++0x是否修复了这个问题;我不认为它有这样做。 - Lightness Races in Orbit
2
@Xeo:我同意提供一个重载函数,它可以接受std::stringc_str()并将其传递给该函数的C字符串版本,这是有意义的。 - AnT stands with Russia
2
你经常需要在运行时构建路径名。似乎std::string非常适合。你说“库的作者认为他们不需要一个运行时可调整大小的字符串来表示文件名”,你有参考资料还是这只是猜测? - idz
2
我同意这个答案的观点。但据我所听,委员会并没有这个理由。这只是被忽视了。 - Johannes Schaub - litb
1
传递非可更改序列的最少界面要求,既不是采用std::string,也不是const char*,而是采用一对迭代器。 - R. Martinho Fernandes
显示剩余16条评论

3
我的猜测是,iostream层次结构/库(包括(i|o)fstream)是在std::string之外发明/开发的,它们只有在放在std库中时才第一次相遇。
在发明iostream的时候,可能有许多不同的string实现正在流传,为了支持最大的可移植性,他们决定押注于一种始终可用的数据类型,即简单的char const* C风格字符串。

2
浏览了我的G++的头文件后,我注意到所有对std::basic_string或其任何typedef的引用都在以#ifdef __GXX_EXPERIMENTAL_CXX0X__为界限的部分中。
这使我想到iostreams库的设计是独立于string库的,因此如果您不使用std::string,则不必为其付费(这在C ++中历史上一直是非常重要的设计原则)。这也可以解释为什么getline(std::istream&, std::string&)是在中定义的自由函数,而不是像istream::getline(char*,streamsize)一样的成员函数。
这也表明,在C++0x标准化中,将iostreams库与string库分离被视为设计缺陷,并决定不值得为此付出不便。

现在,你可以感到困扰了 ;-] http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3290.pdf - ildjarn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接