std::cout
对象在iostream
头文件中声明为
namespace std _GLIBCXX_VISIBILITY(default)
{
...
extern ostream cout;
...
}
从现在开始,我放弃了std::
前缀。
所以,据我所知,cout
是"只是"类型为ostream
的对象。我开始想知道为什么用cout
而不是其他ostream
对象打印到屏幕的东西,所以我试图创建一个ostream
类型的对象,但编译器不会让我。事实上,ostream
只是basic_ostream<char>
的别名,并且该类型的默认构造函数受到保护。很好,我想。但后来我想知道:为什么cout
的声明合法开始?为什么不发出编译错误?
我再次尝试使用关键字ostream
声明extern
,例如
extern ostream os;
os << "Will you compile?\n";
这次我得到了os的未定义引用错误。然后问题就转移到以下问题:是否有一个&#39;定义&#39;其他地方的cout
?如果是这样,在哪里?
我无法理解这一点。我知道,出于性能和安全原因,标准标题是用一种“神秘的”字体写成的。方式,除非你完全掌握语言(我仍然不太可能),但并不总是易于阅读,但我想了解这一点。
感谢。
答案 0 :(得分:5)
我开始想知道为什么用cout打印屏幕的东西而不是其他ostream对象,
因为std::cout
使用与stdout
设备关联的流缓冲区。
所以我尝试创建一个ostream类型的对象,但编译器不会让我。事实上,ostream只是basic_ostream的别名,并且该类型的默认构造函数受到保护。很好,我想。但后来我想知道:为什么宣布cout合法开始?为什么不发出编译错误?
因为它是一个声明,而不是一个定义,所以它不会调用任何构造函数。也许您应该阅读extern
对声明的含义。
extern
声明只是说在程序中的某个地方定义了一个对象ostream
并且称为cout
。由于您实际上没有提供任何此类定义,因此会出现链接器错误。
要近似模拟std::cout
,您可以在某个.cpp
文件中执行此操作:
namespace {
std::ofstream fake_cout("/dev/stdout");
}
std::ostream cout(fake_cout.rdbuf());
这会创建一个写入fstream
的{{1}},然后将名为/dev/stdout
的{{1}}与其流缓冲区相关联。
这不是对真实ostream
的良好模拟,因为它不能确保在任何其他全局变量尝试使用它之前初始化流,这是真实的。
答案 1 :(得分:4)
是否有&#39;定义&#39;在其他地方的cout?如果是这样,在哪里?
是的,标准C ++库的libstdc ++实现中有cout
的定义。该定义不是以在标准C ++中有效的方式完成的。没关系,因为标准C ++库的实现不必用标准C ++编写,只需要以实现其余部分理解的方式编写。