They're needed to ensure the correct initialization of the
standard iostream objects, like std::cout
. Basically, the
standard iostream objects are guaranteed to be constructed by
the time the first constructor of ios_base::Init
has finished.
(The init_cnt
member is part of one technique of achieving
this.) In addition, the standard says that including
<iostream>
declares a static instance of ios_base::Init
(or
behaves as if it does), so if you write:
#include <iostream>
class X
{
public:
X() { std::cout << "something";
};
X anXwithStaticLifetime;
you're guaranteed that std::cout
will be constructed before
the constructor of anXwithStaticLifetime
is run.
Of course, this only works within a single translation unit. If
you define in a header ("X.hh"):
class X
{
public:
X();
};
and then in two different translation units:
#include "X.hh"
#include <iostream>
X::X()
{
std::cout << "something";
}
and:
#include "X.hh"
X anXwithStaticLifetime;
it's quite possible that std::cout
will not have been
constructed when you execute the constructor. The usual way of
ensuring this is to define a local instance of ios_base::Init
in the constructor:
X::X()
{
static ios_base::Init toEnsureInitialization;
std::cout << "something";
}
In practice, most implementations use additional tricks to
reduce the risk. But as far as I know, none of them are 100%,
and depending on how you link, you can still get into problems.
But they won't occur if you do things the usual way. With the
results that a lot of programmers aren't aware of the risk, and
don't make the necessary declaration (and it almost always works
anyway).
Init
class exists at all? From your link - so that standard stream objects "are constructed and properly initialized." Why does that matter? Cos globals are evil.operator<<
oncout
, its must already be a valid object. Which means it must have been previously constructed.