I read effective C++ which item 04 mentioned
Avoid initialization order problems across translation units by re-placing non-local static objects with local static objects.
I think that "global and only-one object" should be singleton pattern, not extern object after I read this item.
such as I/O object(std::cout)
But std::cout seems extern object. (http://www.cplusplus.com/reference/iostream/cout/)
I am confused about this.
I Capture some code form this book.
First is bad code:
class FileSystem {
// from your library’s header file
public:
...std::size_t numDisks( ) const;
// one of many member functions...
};
extern FileSystem tfs;
the relative order of initialization of non-local staticobjects defined in different translation units is undefined.
So abovementioned code may be fault when I call tfs.
Because tfs may not complete initialization.
The recommand code:
class FileSystem { ... }; // as before
FileSystem& tfs()
{
static FileSystem fs;
return fs;
}
class Directory { ... };// as beforeDirectory::Directory( params )
Directory::Directory( params ) // as before, except references to tfs are
//now to tfs( )
{
...
std::size_t disks = tfs().numDisks( );
...
}
Directory& tempDir()
{
static Directory td(params);
return td;
}
Using an extern
variable allows the (subjectively) nicer syntax of
std::cout << stuff;
Emphasizing that the standard stream is a unique object and not the result of some function call. Since streaming is meant to be done into stream objects, using object notation ties better into it.
As for the static initialization order fiasco, the standard library avoids it by using the Schwarz Counter technique for initialization. Initialization happens in a well defined order because including iostream
adds a special global object of type Init
to the including TU. The object's constructor handles the initialization of the stream before its first use, wherever that first use may be.