关于std::cout,为什么用"extern"而不是"singleton pattern"
About std::cout, why use "extern" rether than "singleton pattern"
我阅读了 effective C++ 项目 04 提到的
Avoid initialization order problems across translation units by re-placing non-local static objects with local static objects.
看完这篇我觉得"global and only-one object"应该是单例模式,而不是extern object
例如I/O对象(std::cout)
但是std::cout似乎是外部对象。
(http://www.cplusplus.com/reference/iostream/cout/)
我对此很困惑。
编辑:添加代码
我从这本书中获取了一些代码。
首先是错误的代码:
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.
所以上面的代码在我调用tfs时可能是错误的。
因为tfs可能没有完成初始化
推荐代码:
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;
}
使用 extern
变量允许
的(主观上)更好的语法
std::cout << stuff;
强调标准流是一个独特的对象,而不是某些函数调用的结果。由于流式传输是要在流对象中完成的,因此使用对象表示法可以更好地融入其中。
至于静态初始化顺序的失败,标准库通过对包括 TU 使用 Schwarz Counter technique for initialization. Initialization happens in a well defined order because including iostream
adds a special global object of type Init
来避免它。对象的构造函数在首次使用之前处理流的初始化,无论首次使用是在何处。
因为 C++ 选择了一种更精细的方法,获得了直接对象访问的效率和简单性,同时仍然避免了静态初始化顺序的失败。
如何?
C++ 标准流实际上并不是静态初始化的。相反,#include-ing <iostream>
defines a global static object of type std::ios_base::Init
管理全局 reference-count,并用它来初始化 C++ 流。
或者至少,它是这样指定的,但总有 as-if rule。
我阅读了 effective C++ 项目 04 提到的
Avoid initialization order problems across translation units by re-placing non-local static objects with local static objects.
看完这篇我觉得"global and only-one object"应该是单例模式,而不是extern object
例如I/O对象(std::cout)
但是std::cout似乎是外部对象。 (http://www.cplusplus.com/reference/iostream/cout/)
我对此很困惑。
编辑:添加代码
我从这本书中获取了一些代码。
首先是错误的代码:
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.
所以上面的代码在我调用tfs时可能是错误的。
因为tfs可能没有完成初始化
推荐代码:
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;
}
使用 extern
变量允许
std::cout << stuff;
强调标准流是一个独特的对象,而不是某些函数调用的结果。由于流式传输是要在流对象中完成的,因此使用对象表示法可以更好地融入其中。
至于静态初始化顺序的失败,标准库通过对包括 TU 使用 Schwarz Counter technique for initialization. Initialization happens in a well defined order because including iostream
adds a special global object of type Init
来避免它。对象的构造函数在首次使用之前处理流的初始化,无论首次使用是在何处。
因为 C++ 选择了一种更精细的方法,获得了直接对象访问的效率和简单性,同时仍然避免了静态初始化顺序的失败。
如何?
C++ 标准流实际上并不是静态初始化的。相反,#include-ing <iostream>
defines a global static object of type std::ios_base::Init
管理全局 reference-count,并用它来初始化 C++ 流。
或者至少,它是这样指定的,但总有 as-if rule。