2008-08-28 57 views
34

这不是一个设计问题,确实如此,尽管看起来可能如此。 (好吧,这是一个设计问题)。我想知道的是为什么C++ std::fstream类不在其构造函数或开放方法中使用std::string。每个人都喜欢这样的代码示例:为什么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

回答

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 s和fstream s。假设C字符串可以转换为std::strings,就像当前标准中的状态一样。现在,考虑以下因素:

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

该示例不应对重载解析规则造成任何歧义。 `f(char *,std :: string)`是[精确匹配](http://www.lcdf.org/c++/clause13.html#s13.3.3.1.1),而其他的则需要转换,因此首先是最好的可行功能。如果你删除了第一个`f`,那么就像[(char *&,std :: string&) - >(char *,std :: string) - >(char *,char *))[更好的转换序列](http://www.lcdf.org/c++/clause13.html#s13.3.3)比“(char *&,std :: string&) - >(char *,std :: string) - >(std: :string,char *)“,第二个`f`将是最好的可行函数。我错过了什么吗? – outis 2010-11-14 23:49:43

0

STL中是否有需要字符串的类...我不这么认为(在我的快速搜索中找不到任何类)。所以这可能是一些设计决定,STL中的任何类都不应该依赖于任何其他STL类(这不是功能直接需要的)。

14

有几个地方C++标准委员会没有真正优化标准库中设施之间的交互。

std::string它在图书馆中的使用就是其中之一。

另一个例子是std::swap。许多容器都具有交换成员函数,但不提供std :: swap的重载。 std::sort也是如此。

我希望所有这些小东西都会在即将到来的标准中得到解决。

0

我相信这已经被考虑过,并且是为了避免依赖;即#include <fstream>不应强制#include <字符串>。

说实话,这似乎是一个相当不重要的问题。更好的问题是,为什么std :: string的界面如此之大?

2

这是不重要的,那是真的。 std :: string的接口很大是什么意思?在这种情况下,大的含义是什么 - 大量的方法调用?我并不是一个人,我真的很感兴趣。

它有比实际需要更多的方法,它使用积分偏移而不是迭代器的行为有点不确定(因为它与库的其余部分的工作方式相反)。

我认为真正的问题是C++库有三个部分;它有旧的C库,它有STL,它有字符串和iostreams。尽管已经做了一些工作来弥补不同的部分(例如,为C库添加了重载,因为C++支持重载;向basic_string添加迭代器;添加了iostream迭代器适配器),但是当您存在很多不一致时看看细节。

例如,basic_string包括标准算法不必要的重复方法;各种查找方法,可能可以安全地删除。另一个例子:语言环境使用原始指针而不是迭代器。

3

@ Bernard:
Monoliths“Unstrung”。 “一切为了所有人”可能适用于火枪手,但对于班级设计师来说,这种方式几乎没有效果。下面是一个不完全示范的例子,它说明了当设计变成过度设计时,你会错多少。这个例子是,不幸的是,从你附近的一个标准库取... 〜http://www.gotw.ca/gotw/084.htm

11

也许这是一个安慰:所有的fstream的已经得到了一个开放的(字符串常量&,...)旁开(字符常量*,...)在C++ 0x标准的工作草案中。 (例如参见27.8.1.6为basic_ifstream声明)

因此,当它被敲定并执行,就不会得到你了:)

9

流IO库已被添加到C++标准库前STL。为了不破坏向后兼容性,已经决定避免在添加STL时修改IO库,即使这意味着您提出的问题。

1

C++在小型机器上长大,比我们今天编写代码的怪物长大。当iostream是新的时候,许多开发人员真的关心代码大小(他们必须将他们的整个程序和数据放入几百KB)。因此,许多人不想拉入“大”的C++字符串库。许多人甚至没有使用iostream库的代码大小相同的原因。

我们没有像现在这样做的数千兆内存。我们通常没有函数级链接,因此我们受库开发人员的束缚,无法使用大量单独的对象文件,或者引入大量未调用的代码。所有这些FUD都使开发人员避开了std :: string。

那时我回避了std :: string。 “太臃肿”,“过于频繁地调用malloc”等。愚蠢地使用基于堆栈的缓冲区来处理字符串,然后添加各种繁琐的代码以确保它不会溢出。

0

现在,您可以非常轻松地解决此问题:将-std=c++11添加到您的CFLAGS

相关问题