Yes, this is normal, not UB. The use of streams declared in iostream is clearly defined by the standard.
27.4 Standard iostream objects
2 Objects are built, and associations are established for some time before or during the first when the object of the ios_base::Init class is built , and in any case, before the main body starts execution. 293 Objects are not destroyed during program execution .294 The results of including <iostream> in the translation block should be as if <iostream> determined an instance of ios_base::Init with a static storage duration. In the same way, the whole program should behave as if there was at least one instance of ios_base::Init with a duration of static storage.
Thus, the standard requires that cout initialized before the first creation of ios_base::Init and #include<iostream> , ensuring that it is there. Thus, by turning on iostream, you implicitly define a static instance of ios_base::Init and ensure that cout will work correctly.
Note 294 also explicitly states that constructors and destructors of static objects are allowed to use these objects.
294) Constructors and destructors for static objects can access these objects to read input from stdin or to output output to stdout or stderr.
C ++ 03 Edit: Although all of the above quotes refer to C ++ 11, C ++ 03 does not have a “define ios_base::Init on iostream include” rule. In C ++ 03, there is still a comment about the constructors and destructors of static objects in # 260 instead of 294, so for C ++ 03 it is still allowed to use cout in the constructor of static objects.
source share