我需要在使用 <iostream> 之外,还需不需要使用 #include <string>?

31
我开始学习C++,读了一本书,上面写着我必须使用<string>头文件,因为字符串类型不是直接内置于编译器中的。如果我使用<iostream>,我就可以使用字符串类型。
如果我已经包含了<iostream>头文件,那么当我想使用字符串类型时,是否必须包含<string>头文件呢?为什么?有什么区别吗?
2个回答

35

是的,你必须包含你使用的头文件。并不是所有标准头文件都会互相包含(有一些例外情况)。现在可能能够工作,但在另一个编译器上可能会失败。

在你的情况下,显然<iostream> 直接或间接包含 <string>,但不要依赖它。


这可能是字符串的前向声明(<ios>包括<iosfwd>,<stringfwd.h>在gcc实现中)。我认为这是标准行为(不过需要检查标准),所以我相信当他不需要完整类型时可以依赖它。 - Aleph
@AnotherTest说:“我可以使用字符串类型” - 告诉我他需要完整的类型。如果不需要,那么前向声明就可以了。 - Luchian Grigore
27.5.1 规定 <iostream> 必须包括 <iosfwd>。这只需要 char_traits,所以我不确定编译器是否还必须前向声明 string。我仍然怀疑任何实现的 iostream 是否都包括整个 string 标头文件。 - Aleph

10
当您想要使用字符串类型时,是否必须包含<string>头文件,即使已经包含<iostream>头文件?是的,是必须的。不能仅仅依赖于相关的头文件(例如<string>)通过其他头文件(例如<iostream>)间接地#include,虽然在某些实现中可能是这种情况。即使这样似乎可以工作,但如果没有导入某些运算符的所有相关重载,或者如果在您#include的头文件中只有关于某个类的前向声明,但是关于该类从某个其他类派生的信息仅包含在未被#include的头文件中,这可能会导致麻烦。例如,请参见此 StackOverflow 上的 Q&A,其中给出了这种情况的示例。

ios_base::getloc 通过值返回 std::locale,而 locale::name 通过值返回 std::string,因此实际上需要 #include <iostream> 来完全定义 std::string。只有 <string> 中的非成员是可选的。 - Cubbi
非常好的观点。我刚遇到一个问题,我们正在使用一些库代码,它依赖于这个问题,当我们从一个非常旧的操作系统/编译器升级到一个更新的版本时,编译会因为“没有明显的原因”而中断。 - user320781

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接