skip to Main Content

std::cout is an instance of std::ostream. I can see the declaration of std::cout in a file named /usr/include/c++/7/iostream:

extern ostream cout;      /// Linked to standard output

And std::ostream is defined by typedef std::basic_ostream<char> std::ostream.

What’s more, it seems that you can’t create an instance of std::ostream. See this demo code snippet:

#include<iostream>

int main()
{
    std::ostream os;
    return 0;
}

Here is what the compiler complains about the code snippet above:

In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/iostream:39:0,
                 from <source>:1:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/ostream: In function 'int main()':
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/ostream:384:7: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char; _Traits = std::char_traits<char>]' is protected
       basic_ostream()
       ^
<source>:5:18: error: within this context
     std::ostream os;
                  ^

The question arises, since the std::basic_ostream<_CharT, _Traits>::basic_ostream() is marked protected, how std::cout is created?

This link on CppReference seems not very meaningful. It does not clearly tell me how std::cout is implemented and how std::cout is created by the constructor of std::ostream. As far as I can see, the most related information is:

The global objects std::cout and std::wcout control output to a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C output stream stdout.

And nothing more.

I am working on Ubuntu with gcc 4.9

Thanks to @NathanPierson.

He told me that

std::basic_ostream has a constructor that takes a pointer to a std::basic_streambuf object.std::cout is initialized using a pointer to an instance of some implementation-defined derived class of std::basic_streambuf.

, which moves me closer to the answer.

3

Answers


  1. A compiler and its standard library implementation may cooperate using non-standard features which are not usable by mere programmers.

    This is not necessary in this case because there is a quite standard public constructor:

    explicit basic_ostream(basic_streambuf<char_type, Traits>* sb);
    

    If you have a streambuf ready, you can create an object of type ostream, and so can the standard library.

    What is that streambuf exactly is a hidden implementation detail, but on a typical implementation it is probably an object of a custom class constructed from stdout (the C-style <cstdio> file pointer).

    Login or Signup to reply.
  2. how std::cout is created?

    First things first, from https://en.cppreference.com/w/cpp/io/ios_base/Init :

    std::ios_base::Init

    This class is used to ensure that the default C++ streams (std::cin,
    std::cout, etc.) are properly initialized and destructed. […]

    The header <iostream> behaves as if it defines (directly or
    indirectly) an instance of std::ios_base::Init with static storage
    duration: […]

    Meh, let’s do a real code example. I will be using GCC C++ library. From https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/iostream#L73 , this is the important part:

     // For construction of filebuffers for cout, cin, cerr, clog et. al.
     static ios_base::Init __ioinit;
    

    Now we jump to the constructor of ios_base::Init class, in https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/c%2B%2B98/ios_init.cc#L85 :

    ios_base::Init::Init()
      {
        if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 1) == 0)
          {
        // Standard streams default to synced with "C" operations.
        _S_synced_with_stdio = true;
    
        new (&buf_cout_sync) stdio_sync_filebuf<char>(stdout);
        new (&buf_cin_sync) stdio_sync_filebuf<char>(stdin);
        new (&buf_cerr_sync) stdio_sync_filebuf<char>(stderr);
    
        // The standard streams are constructed once only and never
        // destroyed.
        new (&cout) ostream(&buf_cout_sync);
        new (&cin) istream(&buf_cin_sync);
        new (&cerr) ostream(&buf_cerr_sync);
        new (&clog) ostream(&buf_cerr_sync);
        cin.tie(&cout);
        cerr.setf(ios_base::unitbuf);
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // 455. cerr::tie() and wcerr::tie() are overspecified.
        cerr.tie(&cout);
    

    The _S_refcount is there for when you would call ios_base::Init::Init(); manually from a constructor of a static class, it protects against double initialization.

    The stdio_sync_filebuf is an internal buffer for istream/ostream and it is meant to handle cstdio FILE* operations to get/put input/output data, with implementation here https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/ext/stdio_sync_filebuf.h#L56 . It inherits from std::basic_streambuf.

    So cout is constructed in-place with stdio_sync_filebuf<char> as parameter. It is the first constructor mentioned here https://en.cppreference.com/w/cpp/io/basic_ostream/basic_ostream .

    Now, because the stuff is constructed in-place, you might wonder how is the memory allocated? From https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/c%2B%2B98/globals_io.cc#L50 :

      // Standard stream objects.
      // NB: Iff <iostream> is included, these definitions become wonky.
      typedef char fake_istream[sizeof(istream)]
      __attribute__ ((aligned(__alignof__(istream))));
      typedef char fake_ostream[sizeof(ostream)]
      __attribute__ ((aligned(__alignof__(ostream))));
      fake_istream cin;
      fake_ostream cout;
      fake_ostream cerr;
      fake_ostream clog;
    

    The objects are just empty char buffers of proper size and proper alignment.

    And yes, you can construct ostream yourself, with __gnu_cxx::stdio_sync_filebuf on GCC:

    #include <fstream>
    #include <ext/stdio_sync_filebuf.h>
    int main() {
        __gnu_cxx::stdio_sync_filebuf<char> mybuf_cout_sync(stdout);
        std::ostream os(&mybuf_cout_sync);
        os << "Hello world!n";
        return 0;
    }
    

    Or, to be portable, you would write your own class that inherits from std::streambuf and construct ostream from it yourself. There are many examples online, like for example here https://stackoverflow.com/a/51250032/9072753 .

    Login or Signup to reply.
  3. I think a part of what the current answers are missing, and what is part of your question:
    the name std::cout is also ‘magical’.
    This means that the standard library knows about it, and provides the OS-specific necessary connections to the terminal; using the respective (and OS-specific) system calls for output, etc.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search