为什么std :: fstream类不采用std :: string?

时间:2008-08-28 14:07:00

标签: c++ stl file-io stdstring

这不是一个设计问题,实际上,虽然它可能看起来像。 (好吧,好吧,这是一个设计问题)。我想知道为什么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吗?

10 个答案:

答案 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