我正在学习C++,我一直在思考为什么会发生这种情况。这段代码将完美地编译和运行,但是如果我取消对//cout << foo << endl;
的注释,它就不会编译。
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string foo = "temporary";
//cout << foo << endl;
// Pause then exit
system("pause");
return 0;
}
我通过添加:#include <string>
来解决它。有人能告诉我为什么这是因为对我来说(来自C#)这没有意义为什么你被允许创建一个字符串对象而不打印它吗?
谢谢!
当您#include <iostream>
时,由标头来包含它想要的任何其他标头以及结果声明和定义-C++标准并不禁止它包含超过提供所需功能所必需的内容。很明显,在您的编译器/版本中,#include <iostream>
还包含了足够多的与string
相关的定义,以知道存在template <
。。。> std::basic_string::basic_string(const char*);
构造函数(std::string
是typedef
到char
的basic_string
的特定实例化),以便您的代码已知有效:
string foo = "temporary";
尽管如此,当你去流式传输foo
时,它显然没有看到匹配的定义ala template <
。。。> std::ostream& operator<<(std::ostream&, const basic_string<
。。。指定如何执行流式处理的>&)
:这就是编译器抱怨的原因。operator<<
的定义可能在<string>
标头中,这就是为什么在流式传输string
之前确实需要它。
您可以通过要求编译器输出而不是删除预处理的文件来观察这一点,这些文件显示了扩展#include
后的翻译单元。您可以在项目的构建配置中找到这样做的选项。
总之,这就是为什么有时代码的包含数可能比严格需要的要少。如果你意识到你已经做到了这一点,那么最好包括其他头文件,确保可移植到其他编译器和同一编译器的未来版本。
根据§21.3[string.classes],使用字符串类、其成员、运算符重载等的标准库文档需要包含<string>
。任何依赖不同的标头这样做的行为,无论是您自己的设备还是其他标头,都是非标准的,除非有文件证明它这样做(包括<string>
)。您正在使用的插入运算符在§21.4.8.9[string.io]中有描述,但最终适用相同的规则:包括<string>
。
您可以推测通过避免使用插入器重载,在不包含<string>
的情况下允许编译成功的原因。也许std::basic_string
的运算符重载是以的方式包含的,而不是通过在实现中简单地包含<iostream>
来实现。
然而,这种猜测最终并没有什么不同。这就是一切:猜测。最终,您的代码没有形成良好的格式,因为您没有按照标准遵循规则,谢天谢地,在这种情况下,这些规则是可以琐碎地寻址的。