这不是一个设计问题,实际上,虽然它可能看起来像。 (好吧,好吧,这是一个设计问题)。我想知道为什么C ++ std::fstream
类在构造函数或开放方法中不使用std::string
。每个人都喜欢代码示例:
#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();
}
这使我一直处理文件。当然,C ++库会尽可能使用std::string
吗?
答案 0 :(得分:26)
通过使用C字符串,C ++ 03 std::fstream
类减少了对std::string
类的依赖。但是,在C ++ 11中,std::fstream
类允许为其构造函数参数传递std::string
。
现在,您可能想知道为什么没有从std:string
到C字符串的透明转换,因此需要C字符串的类仍然可以像std::string
那样使用类{期望std::string
可以使用C字符串。
原因是这会导致转换周期,从而可能导致问题。例如,假设std::string
可以转换为C字符串,以便您可以std::string
使用fstream
s。假设C字符串也可以转换为std::string
s,就像当前标准中的状态一样。现在,请考虑以下事项:
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
}
因为您可以在std::string
和C字符串之间转换,所以对f()
的调用可以解析为两个f()
替换中的任何一个,因此不明确。解决方案是通过明确一个转换方向来打破转换周期,这是STL选择用c_str()
做的。
答案 1 :(得分:14)
有几个地方C ++标准委员会没有真正优化标准库中设施之间的交互。
std::string
及其在图书馆中的使用就是其中之一。
另一个例子是std::swap
。许多容器都有一个交换成员函数,但没有提供std :: swap的重载。 std::sort
也是如此。
我希望所有这些小事都能在即将出台的标准中修复。
答案 2 :(得分:11)
也许这是一个安慰:所有fstream都在C ++ 0x标准的工作草案中的open(char const *,...)旁边打开了(字符串const&amp;,...)。 (参见例如27.8.1.6的basic_ifstream声明)
因此,当它最终确定并实施时,它将不再让你:)
答案 3 :(得分:9)
在STL之前,流IO库已添加到标准C ++库中。为了不破坏向后兼容性,已经决定在添加STL时避免修改IO库,即使这意味着某些问题,例如你提出的问题。
答案 4 :(得分:3)
@ Bernard:
Monoliths“Unstrung。” “一个人,一个一个人”可能适用于火枪手,但它对班级设计师来说几乎没有效果。这是一个不完全堪称典范的例子,它说明了当设计变成过度设计时你会出现多么糟糕的错误。不幸的是,这个例子来自你附近的标准图书馆......
〜http://www.gotw.ca/gotw/084.htm
答案 5 :(得分:2)
这是无关紧要的,这是事实。 std :: string的接口是什么意思?在这种情况下,大的意思是什么 - 很多方法调用?我不是很滑稽,我真的很感兴趣。
它有比实际需要更多的方法,并且它使用整数偏移而不是迭代器的行为有点不确定(因为它与库的其余部分的工作方式相反)。
我认为真正的问题是C ++库有三个部分;它有旧的C库,它有STL,它有字符串和iostreams。虽然一些已作出努力,弥合不同部分(例如,除了重载的C库,因为C ++支持重载;加入迭代器的basic_string的;加入了iostream迭代器适配器),也有很多矛盾,当你的看看细节。
例如,basic_string包含不必要的标准算法重复的方法;可以安全地删除各种查找方法。另一个例子:locales使用原始指针而不是迭代器。
答案 6 :(得分:1)
C ++在小型机器上长大,而不是我们今天编写代码的怪物。当iostream成为新的时候,许多开发人员真正关心代码大小(他们必须将整个程序和数据整合到几百KB)。因此,许多人不想拉入“大”C ++字符串库。许多人甚至没有使用iostream库的原因相同,代码大小。
我们没有像今天这样拥有数千兆字节的内存。我们通常没有功能级链接,因此我们受到库的开发人员的支配,使用大量单独的目标文件,或者引入大量未调用的代码。所有这些FUD都让开发人员远离std :: string。
当时我也避免使用std :: string。 “过于膨胀”,“经常称为malloc”等。愚蠢地使用基于堆栈的字符串缓冲区,然后添加各种繁琐的代码以确保它不会溢出。
答案 7 :(得分:0)
STL中是否有任何带字符串的类...我不这么认为(在我的快速搜索中找不到任何内容)。所以这可能是一些设计决定,STL中的任何类都不应该依赖于任何其他STL类(功能不直接需要)。
答案 8 :(得分:0)
我认为这是为了避免依赖而被考虑和完成的;即#include&lt; fstream&gt;不应强迫一个人#include&lt; string&gt;。
说实话,这似乎是一个非常无关紧要的问题。一个更好的问题是,为什么std :: string的界面如此之大?
答案 9 :(得分:0)
现在您可以非常轻松地解决此问题:将-std=c++11
添加到CFLAGS
。