36

这不是一个设计问题,真的,虽然看起来很像。(嗯,好吧,这是一个设计问题)。我想知道的是为什么 C++std::fstream类不在std::string其构造函数或开放方法中采用 a。每个人都喜欢代码示例,所以:

#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尽可能使用吗?

4

10 回答 10

26

通过采用 C 字符串,C++03std::fstream类减少了对该类的依赖std::string。然而,在 C++11 中,该类确实允许为其构造函数参数std::fstream传递 a 。std::string

现在,您可能想知道为什么没有从 astd:string到 C 字符串的透明转换,所以期望 C 字符串的类仍然可以采用 a std::string,就像期望 astd::string可以采用 C 字符串的类一样。

原因是这会导致转换周期,进而可能导致问题。例如,假设std::string可以转换为 C 字符串,以便您可以将std::strings 与fstreams 一起使用。还假设 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
}

因为您可以在 astd::string和 C 字符串之间转换任何一种方式,所以调用f()可以解析为两种f()选择中的任何一种,因此是模棱两可的。解决方案是通过明确一个转换方向来中断转换周期,这是 STL 选择使用c_str().

于 2008-09-01T06:53:24.820 回答
14

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

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

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

我希望所有这些小问题都将在即将发布的标准中得到解决。

于 2008-08-28T14:18:08.947 回答
11

也许这是一个安慰:在 C++0x 标准的工作草案中,所有 fstream 都在 open(char const *, ...) 旁边获得了一个 open(string const &, ...)。(有关 basic_ifstream 声明,请参见例如 27.8.1.6)

因此,当它最终确定并实施时,它不会再吸引您了 :)

于 2008-09-15T13:43:44.480 回答
9

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

于 2008-09-16T15:31:57.223 回答
3

@伯纳德:
巨石“松散”。“一劳永逸,一劳永逸”可能适用于火枪手,但它几乎不适用于职业设计师。这是一个并非完全具有示范性的示例,它说明了当设计变成过度设计时,您可能会出错的严重程度。不幸的是,该示例取自您附近的标准库...〜http ://www.gotw.ca/gotw/084.htm

于 2008-09-15T13:26:24.850 回答
2

这是无关紧要的,这是真的。std::string 的接口很大是什么意思?在这种情况下,大意味着什么 - 大量的方法调用?我不是在开玩笑,我真的很感兴趣。

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

我认为真正的问题是 C++ 库包含三个部分;它有旧的 C 库,有 STL,还有字符串和 iostream。尽管已经做了一些努力来连接不同的部分(例如,向 C 库添加重载,因为 C++ 支持重载;向 basic_string 添加迭代器;添加 iostream 迭代器适配器),但当您使用看看细节。

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

于 2008-08-28T14:39:40.860 回答
1

C++ 是在比我们今天编写代码的怪物更小的机器上长大的。回到 iostream 刚出现时,许多开发人员真的很关心代码大小(他们必须将整个程序和数据放入数百 KB)。因此,许多人不想引入“大”C++ 字符串库。出于同样的原因,许多人甚至没有使用 iostream 库,即代码大小。

我们没有像今天这样扔掉数千兆字节的 RAM。我们通常没有函数级链接,因此我们只能任由库的开发人员使用大量单独的目标文件或引入大量未调用的代码。所有这些 FUD 都使开发人员远离 std::string。

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

于 2012-11-10T22:36:58.673 回答
0

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

于 2008-08-28T14:14:24.447 回答
0

我相信已经考虑过并这样做是为了避免依赖;即#include <fstream> 不应该强制一个#include <string>。

老实说,这似乎是一个无关紧要的问题。一个更好的问题是,为什么 std::string 的接口这么大?

于 2008-08-28T14:28:52.883 回答
0

现在你可以很容易地解决这个问题:添加-std=c++11到你的CFLAGS.

于 2016-03-10T19:09:52.350 回答