Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does std::cout declaration work?

Tags:

c++

cout

The std::cout object is declared in the iostream header file as

namespace std _GLIBCXX_VISIBILITY(default)
{
...
extern ostream cout;
...
}

From now on I'm dropping the std:: prefix.

So, as far as I understand, cout is "just" an object of type ostream. I started to wonder why stuff is printed to screen with cout and not with other ostream objects, so I tried to create an object of type ostream, but the compiler would not let me. As a matter of fact, ostream is just an alias for basic_ostream<char>, and the default constructor for that type is protected. Fine, I thought. But then I wondered: why is the declaration of cout legal to start with? Why doesn't that issue a compiler error?

I tried again to declare an ostream with the keyword extern, such as

extern ostream os;
os << "Will you compile?\n";

and this time I got the undefined reference error to os. Then the question just moves to the following: is there a 'definition' of cout somewhere else? If so, where?

I can't get my head around this. I know that, for performance and safety reasons, the standard header are written in a kind of "cryptic" way, not always easy to read unless you fully and completely master the language (which I still don't probably), but I'd like to understand this bit.

Thanks.

like image 654
bartgol Avatar asked Jun 03 '26 17:06

bartgol


2 Answers

I started to wonder why stuff is printed to screen with cout and not with other ostream objects,

Because std::cout uses a stream buffer that is associated with the stdout device.

so I tried to create an object of type ostream, but the compiler would not let me. As a matter of fact, ostream is just an alias for basic_ostream, and the default constructor for that type is protected. Fine, I thought. But then I wondered: why is the declaration of cout legal to start with? Why doesn't that issue a compiler error?

Because it's a declaration, not a definition, so it doesn't invoke any constructor. Maybe you should read about what extern means on a declaration.

The declaration with extern just says there is an object defined somewhere else in the program that is of type ostream and called cout. Since you didn't actually provide any such definition you get linker errors.

To approximately simulate std::cout you could do this in some .cpp file:

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

This creates an fstream that writes to /dev/stdout then associates the ostream called cout with its stream buffer.

This isn't a good simulation of the real std::cout because it doesn't ensure that the stream is initialized before any other globals try to use it, which the real one does.

like image 71
Jonathan Wakely Avatar answered Jun 06 '26 10:06

Jonathan Wakely


is there a 'definition' of cout somewhere else? If so, where?

Yes, there is a definition of cout in the libstdc++ implementation of the standard C++ library. This definition is not done in a way that's valid in standard C++. That's okay, because the implementation of the standard C++ library doesn't have to be written in standard C++, it just has to be written in a way that the rest of the implementation understands.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!