我阅读了第04项提到的有效的C ++
通过用本地静态对象替换非本地静态对象,避免跨翻译单元的初始化顺序问题。
我认为“全局且只有一个对象”应该是单例模式,而不是在阅读了此项目之后的外部对象。
例如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;
在不同翻译单元中定义的非局部静态对象的初始化相对顺序不确定。
因此,当我调用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;
}
答案 0 :(得分:0)
使用extern
变量可以使(主观上)更好的语法
std::cout << stuff;
强调标准流是唯一的对象,而不是某些函数调用的结果。由于流是要在流对象中完成的,因此使用对象符号可以更好地将其绑定到其中。
对于静态初始化顺序失败,标准库通过使用Schwarz Counter技术进行初始化来避免它。初始化按定义良好的顺序进行,因为包含iostream
向包含的TU添加了类型为Init
的特殊全局对象。该对象的构造函数会在首次使用流之前处理流的初始化,无论该第一次使用在哪里。
答案 1 :(得分:0)
因为C ++选择了一种更为复杂的方法,因此可以提高直接对象访问的效率和简便性,并且仍然避免了静态初始化顺序的惨败。
如何?
c ++标准流实际上不是静态初始化的。相反,#include-ing <iostream>
定义了类型为std::ios_base::Init
的全局静态对象,该对象管理全局引用计数,并由此管理C ++流。
或者至少是这样指定的,但是总是有as-if rule。