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的未定义引用错误。然后问题就转移到以下地方:在其他地方是否存在cout的“定义”?如果是这样,在哪里?

我无法解决这个问题。我知道,出于性能和安全性的考虑,标准 header 以一种“神秘”的方式编写,除非您完全完全掌握了该语言(我仍然不太可能),否则它并不总是易于阅读,但是我d想了解这一点。

谢谢。

最佳答案



因为std::cout使用与stdout设备关联的流缓冲区。



因为它是声明,而不是定义,所以它不会调用任何构造函数。也许您应该阅读extern在声明中的含义。

带有extern的声明仅表示在程序的其他位置定义了一个对象,该对象的类型为ostream,称为cout。由于您实际上未提供任何此类定义,因此会出现链接器错误。

要大致模拟std::cout,可以在一些.cpp文件中执行以下操作:

namespace {
  std::ofstream fake_cout("/dev/stdout");
}
std::ostream cout(fake_cout.rdbuf());

这将创建一个fstream并写入/dev/stdout,然后将名为ostreamcout与它的流缓冲区相关联。

这不是真实的std::cout的良好模拟,因为它不能确保在任何其他全局变量尝试使用它之前就初始化该流,真实的人会这样做。

10-08 09:17
查看更多