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

时间:2023-02-07 11:29:41

This isn't a design question, really, though it may seem like it. (Well, okay, it's kind of a design question). What I'm wondering is why the C++ std::fstream classes don't take a std::string in their constructor or open methods. Everyone loves code examples so:

这并不是一个设计问题,虽然看起来是这样的。(好的,这是个设计问题)我想知道的是,为什么c++ std::fstream类在构造函数或open方法中不使用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();
}

This gets me all the time when working with files. Surely the C++ library would use std::string wherever possible?

这让我在处理文件时得到了所有的时间。如果可能,c++库肯定会使用std::string ?

10 个解决方案

#1


26  

By taking a C string the C++03 std::fstream class reduced dependency on the std::string class. In C++11, however, the std::fstream class does allow passing a std::string for its constructor parameter.

通过使用C字符串c++ 03 std::fstream类减少了对std::string类的依赖。但是,在c++ 11中,std::fstream类允许为其构造函数参数传递std::string。

Now, you may wonder why isn't there a transparent conversion from a std:string to a C string, so a class that expects a C string could still take a std::string just like a class that expects a std::string can take a C string.

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

The reason is that this would cause a conversion cycle, which in turn may lead to problems. For example, suppose std::string would be convertible to a C string so that you could use std::strings with fstreams. Suppose also that C string are convertible to std::strings as is the state in the current standard. Now, consider the following:

原因是这将导致一个转换周期,这反过来可能导致问题。例如,假设std::string可以转换为C字符串,以便使用带有fstreams的std::string。假设C字符串可以转换为std::string,这是当前标准中的状态。现在,考虑以下:

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
}

Because you can convert either way between a std::string and a C string the call to f() could resolve to either of the two f() alternatives, and is thus ambiguous. The solution is to break the conversion cycle by making one conversion direction explicit, which is what the STL chose to do with c_str().

因为可以在std::string和C string之间任意转换,所以对f()的调用可以解析为两个f()选项中的任何一个,因此是不明确的。解决方案是通过使一个转换方向显式地打破转换周期,这就是STL选择用c_str()来做的事情。

#2


14  

There are several places where the C++ standard committee did not really optimize the interaction between facilities in the standard library.

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

std::string and its use in the library is one of these.

std::string及其在库中的使用就是其中之一。

One other example is std::swap. Many containers have a swap member function, but no overload of std::swap is supplied. The same goes for std::sort.

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

I hope all these small things will be fixed in the upcoming standard.

我希望所有这些小事情都能在即将到来的标准中得到解决。

#3


11  

Maybe it's a consolation: all fstream's have gotten an open(string const &, ...) next to the open(char const *, ...) in the working draft of the C++0x standard. (see e.g. 27.8.1.6 for the basic_ifstream declaration)

也许这是一种安慰:在c++ 0x标准的工作草案中,所有fstream都在open(char const *,…)旁边有一个open(string const &,…)。(请参见basic_ifstream声明)

So when it gets finalised and implemented, it won't get you anymore :)

因此,当它最终敲定并付诸实施时,你将再也得不到它:

#4


9  

The stream IO library has been added to the standard C++ library before the STL. In order to not break backward compatibility, it has been decided to avoid modifying the IO library when the STL was added, even if that meant some issues like the one you raise.

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

#5


3  

@ Bernard:
Monoliths "Unstrung." "All for one, and one for all" may work for Musketeers, but it doesn't work nearly as well for class designers. Here's an example that is not altogether exemplary, and it illustrates just how badly you can go wrong when design turns into overdesign. The example is, unfortunately, taken from a standard library near you... ~ http://www.gotw.ca/gotw/084.htm

@伯纳德:巨石“解开”。“人人为我,人人为我”可能对火枪手管用,但对职业设计师来说就没那么管用了。这里有一个例子,它并不是完全的模范,它说明了当设计变成过度设计时,你会犯多么严重的错误。不幸的是,这个例子来自您附近的一个标准库……~ http://www.gotw.ca/gotw/084.htm

#6


2  

It is inconsequential, that is true. What do you mean by std::string's interface being large? What does large mean, in this context - lots of method calls? I'm not being facetious, I am actually interested.

这是无关紧要的,这是真的。你说的std::string的接口很大是什么意思?在这个上下文中,big是什么意思——许多方法调用?我不是在开玩笑,我真的很感兴趣。

It has more methods than it really needs, and its behaviour of using integral offsets rather than iterators is a bit iffy (as it's contrary to the way the rest of the library works).

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

The real issue I think is that the C++ library has three parts; it has the old C library, it has the STL, and it has strings-and-iostreams. Though some efforts were made to bridge the different parts (e.g. the addition of overloads to the C library, because C++ supports overloading; the addition of iterators to basic_string; the addition of the iostream iterator adaptors), there are a lot of inconsistencies when you look at the detail.

我认为真正的问题是c++库有三个部分;它有旧的C库、STL和string -and-iostreams。虽然我们做了一些工作来连接不同的部分(例如向C库添加重载,因为c++支持重载;将迭代器添加到basic_string;添加了iostream迭代器适配器),当您查看细节时,会发现有很多不一致之处。

For example, basic_string includes methods that are unnecessary duplicates of standard algorithms; the various find methods, could probably be safely removed. Another example: locales use raw pointers instead of iterators.

例如,basic_string包含的方法是标准算法不必要的重复;各种各样的发现方法,可能会被安全地删除。另一个示例:locale使用原始指针而不是迭代器。

#7


1  

C++ grew up on smaller machines than the monsters we write code for today. Back when iostream was new many developers really cared about code size (they had to fit their entire program and data into several hundred KB). Therefore, many didn't want to pull in the "big" C++ string library. Many didn't even use the iostream library for the same reasons, code size.

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

We didn't have thousands of megabytes of RAM to throw around like we do today. We usually didn't have function level linking so we were at the mercy of the developer of the library to use a lot of separate object files or else pull in tons of uncalled code. All of this FUD made developers steer away from std::string.

我们没有像今天这样有几千兆字节的内存。我们通常没有函数级的链接,所以我们只能依靠库的开发人员来使用大量的单独的对象文件,否则就会产生大量未调用的代码。所有这些FUD使开发人员远离std::string。

Back then I avoided std::string too. "Too bloated", "called malloc too often", etc. Foolishly using stack-based buffers for strings, then adding all kinds of tedious code to make sure it doesn't overrun.

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

#8


0  

Is there any class in STL that takes a string... I dont think so (couldnt find any in my quick search). So it's probably some design decision, that no class in STL should be dependent on any other STL class (that is not directly needed for functionality).

STL中有任何类需要字符串吗?我想没有(在我的快速搜索中找不到)。因此,这可能是一些设计决策,STL中的任何类都不应该依赖于任何其他STL类(这不是功能性的直接需求)。

#9


0  

I believe that this has been thought about and was done to avoid the dependency; i.e. #include <fstream> should not force one to #include <string>.

我相信这已经被考虑过了,而且是为了避免依赖;也就是说,#include 不应该强制一个到#include

To be honest, this seems like quite an inconsequential issue. A better question would be, why is std::string's interface so large?

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

#10


0  

Nowadays you can solve this problem very easily: add -std=c++11 to your CFLAGS.

现在您可以很容易地解决这个问题:在CFLAGS中添加-std=c++11。

#1


26  

By taking a C string the C++03 std::fstream class reduced dependency on the std::string class. In C++11, however, the std::fstream class does allow passing a std::string for its constructor parameter.

通过使用C字符串c++ 03 std::fstream类减少了对std::string类的依赖。但是,在c++ 11中,std::fstream类允许为其构造函数参数传递std::string。

Now, you may wonder why isn't there a transparent conversion from a std:string to a C string, so a class that expects a C string could still take a std::string just like a class that expects a std::string can take a C string.

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

The reason is that this would cause a conversion cycle, which in turn may lead to problems. For example, suppose std::string would be convertible to a C string so that you could use std::strings with fstreams. Suppose also that C string are convertible to std::strings as is the state in the current standard. Now, consider the following:

原因是这将导致一个转换周期,这反过来可能导致问题。例如,假设std::string可以转换为C字符串,以便使用带有fstreams的std::string。假设C字符串可以转换为std::string,这是当前标准中的状态。现在,考虑以下:

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
}

Because you can convert either way between a std::string and a C string the call to f() could resolve to either of the two f() alternatives, and is thus ambiguous. The solution is to break the conversion cycle by making one conversion direction explicit, which is what the STL chose to do with c_str().

因为可以在std::string和C string之间任意转换,所以对f()的调用可以解析为两个f()选项中的任何一个,因此是不明确的。解决方案是通过使一个转换方向显式地打破转换周期,这就是STL选择用c_str()来做的事情。

#2


14  

There are several places where the C++ standard committee did not really optimize the interaction between facilities in the standard library.

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

std::string and its use in the library is one of these.

std::string及其在库中的使用就是其中之一。

One other example is std::swap. Many containers have a swap member function, but no overload of std::swap is supplied. The same goes for std::sort.

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

I hope all these small things will be fixed in the upcoming standard.

我希望所有这些小事情都能在即将到来的标准中得到解决。

#3


11  

Maybe it's a consolation: all fstream's have gotten an open(string const &, ...) next to the open(char const *, ...) in the working draft of the C++0x standard. (see e.g. 27.8.1.6 for the basic_ifstream declaration)

也许这是一种安慰:在c++ 0x标准的工作草案中,所有fstream都在open(char const *,…)旁边有一个open(string const &,…)。(请参见basic_ifstream声明)

So when it gets finalised and implemented, it won't get you anymore :)

因此,当它最终敲定并付诸实施时,你将再也得不到它:

#4


9  

The stream IO library has been added to the standard C++ library before the STL. In order to not break backward compatibility, it has been decided to avoid modifying the IO library when the STL was added, even if that meant some issues like the one you raise.

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

#5


3  

@ Bernard:
Monoliths "Unstrung." "All for one, and one for all" may work for Musketeers, but it doesn't work nearly as well for class designers. Here's an example that is not altogether exemplary, and it illustrates just how badly you can go wrong when design turns into overdesign. The example is, unfortunately, taken from a standard library near you... ~ http://www.gotw.ca/gotw/084.htm

@伯纳德:巨石“解开”。“人人为我,人人为我”可能对火枪手管用,但对职业设计师来说就没那么管用了。这里有一个例子,它并不是完全的模范,它说明了当设计变成过度设计时,你会犯多么严重的错误。不幸的是,这个例子来自您附近的一个标准库……~ http://www.gotw.ca/gotw/084.htm

#6


2  

It is inconsequential, that is true. What do you mean by std::string's interface being large? What does large mean, in this context - lots of method calls? I'm not being facetious, I am actually interested.

这是无关紧要的,这是真的。你说的std::string的接口很大是什么意思?在这个上下文中,big是什么意思——许多方法调用?我不是在开玩笑,我真的很感兴趣。

It has more methods than it really needs, and its behaviour of using integral offsets rather than iterators is a bit iffy (as it's contrary to the way the rest of the library works).

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

The real issue I think is that the C++ library has three parts; it has the old C library, it has the STL, and it has strings-and-iostreams. Though some efforts were made to bridge the different parts (e.g. the addition of overloads to the C library, because C++ supports overloading; the addition of iterators to basic_string; the addition of the iostream iterator adaptors), there are a lot of inconsistencies when you look at the detail.

我认为真正的问题是c++库有三个部分;它有旧的C库、STL和string -and-iostreams。虽然我们做了一些工作来连接不同的部分(例如向C库添加重载,因为c++支持重载;将迭代器添加到basic_string;添加了iostream迭代器适配器),当您查看细节时,会发现有很多不一致之处。

For example, basic_string includes methods that are unnecessary duplicates of standard algorithms; the various find methods, could probably be safely removed. Another example: locales use raw pointers instead of iterators.

例如,basic_string包含的方法是标准算法不必要的重复;各种各样的发现方法,可能会被安全地删除。另一个示例:locale使用原始指针而不是迭代器。

#7


1  

C++ grew up on smaller machines than the monsters we write code for today. Back when iostream was new many developers really cared about code size (they had to fit their entire program and data into several hundred KB). Therefore, many didn't want to pull in the "big" C++ string library. Many didn't even use the iostream library for the same reasons, code size.

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

We didn't have thousands of megabytes of RAM to throw around like we do today. We usually didn't have function level linking so we were at the mercy of the developer of the library to use a lot of separate object files or else pull in tons of uncalled code. All of this FUD made developers steer away from std::string.

我们没有像今天这样有几千兆字节的内存。我们通常没有函数级的链接,所以我们只能依靠库的开发人员来使用大量的单独的对象文件,否则就会产生大量未调用的代码。所有这些FUD使开发人员远离std::string。

Back then I avoided std::string too. "Too bloated", "called malloc too often", etc. Foolishly using stack-based buffers for strings, then adding all kinds of tedious code to make sure it doesn't overrun.

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

#8


0  

Is there any class in STL that takes a string... I dont think so (couldnt find any in my quick search). So it's probably some design decision, that no class in STL should be dependent on any other STL class (that is not directly needed for functionality).

STL中有任何类需要字符串吗?我想没有(在我的快速搜索中找不到)。因此,这可能是一些设计决策,STL中的任何类都不应该依赖于任何其他STL类(这不是功能性的直接需求)。

#9


0  

I believe that this has been thought about and was done to avoid the dependency; i.e. #include <fstream> should not force one to #include <string>.

我相信这已经被考虑过了,而且是为了避免依赖;也就是说,#include 不应该强制一个到#include

To be honest, this seems like quite an inconsequential issue. A better question would be, why is std::string's interface so large?

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

#10


0  

Nowadays you can solve this problem very easily: add -std=c++11 to your CFLAGS.

现在您可以很容易地解决这个问题:在CFLAGS中添加-std=c++11。