In what cases and why is this necessary:
class ios_base::Init {
static int init_cnt; // internal static counter (for exposition only)
public:
Init();
~Init();
}
Have it from this site: cpluplus.com - ios_base::init
I read the description and meditated about it, but this did not help much...
It's a workaround for the static initialization order fiasco. Essentially, if you want to use the global stream objects from a static initializer, you can call this to ensure that they're all constructed in time. Runtimes I'm familiar with already do this properly, but technically speaking that's not guaranteed.
(Note also that as of C++11, it is guaranteed.)
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 ofios_base::Init
has finished. (Theinit_cnt
member is part of one technique of achieving this.) In addition, the standard says that including<iostream>
declares a static instance ofios_base::Init
(or behaves as if it does), so if you write:you're guaranteed that
std::cout
will be constructed before the constructor ofanXwithStaticLifetime
is run.Of course, this only works within a single translation unit. If you define in a header ("X.hh"):
and then in two different translation units:
and:
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 ofios_base::Init
in the constructor: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).