静态数据成员是否真的可以进行延迟初始化?

pip*_*pex 3 c++ lazy-loading

是否可以在真正需要时初始化Singleton的实例?

考虑从着名的"设计模式"中获取的这种模式:

class Singleton {
public:
   static Singleton* Instance();
protected:
   Singleton();
private:
   static Singleton* _instance;
}

Singleton* Singleton::_instance = 0; // unit.cpp

static Singleton* Singleton::Instance() {
   if (_instance == 0) {
       _instance = new Singleton;
   }
   return _instance;
}
Run Code Online (Sandbox Code Playgroud)

现在,我认为那里的模式存在问题,如果有人希望将库中的Singleton提供给其他人:如果用户Singleton::Instance()在初始化_instance之前从另一个编译单元调用(例如在静态数据成员初始化期间),然后跟随调用Singleton::Instance()可能会创建Singleton的另一个实例,并产生不需要的结果,因为_instance可能首先被初始化为0.

我认为一种解决方案是以这种方式初始化_instance:

Singleton* Singleton::_instance = Singleton::Instance();
Run Code Online (Sandbox Code Playgroud)

无论如何,这使得初始化对于那些不需要调用Singleton :: Instance()来初始化其静态数据的人来说不是"懒惰".

是否有更好的解决方案,以便在需要Singleton实例时可以进行初始化?

Sum*_*uma 7

动态初始化之前发生静态初始化

你引用的单例解决方案有效

Singleton* Singleton::_instance = 0;
Run Code Online (Sandbox Code Playgroud)

描述了静态初始化(即在这种情况下为零初始化,但如果使用的话,常量初始化也会起作用),这保证在任何动态初始化之前(因此在运行任何代码之前)发生.这里保证了静态初始化的所有要求,因为_instance是内置类型(指针)的全局变量,并用零初始化.

你提供的另一个解决方案没有改变任何重要的东西,因为在调用其他模块的代码之前,仍然只保证_instance的零初始化,因为Singleton :: Instance调用的初始化是动态的,因此受制于静态初始化命令fiasco.

实施 - 数据部分

注意:静态初始化通常通过将变量的值(可编译的编译时间)存储在可执行文件的数据段中来实现.

术语,标准报价

虽然大多数程序员(包括Bjarne Stroustrup)调用原始单例实现"编译时初始化"中使用的初始化样式,但标准称之为"静态初始化",而不是"动态初始化"(这通常称为run -时间).参见C++ 0x draft 3.6.2(缩写,强调我的):

3.6.2非局部变量的初始化 [basic.start.init]

...具有静态存储持续时间的非局部变量由于程序启动而初始化.... 如下.

2具有静态存储持续时间(3.7.1)的变量...在进行任何其他初始化之前应进行零初始化(8.5).

执行常量初始化:...

  • 如果具有静态或线程存储持续时间的对象未通过构造函数调用初始化,并且其初始化程序中出现的每个完整表达式都是常量表达式.

零初始化和常量初始化一起称为静态初始化; 所有其他初始化是动态初始化.在进行任何动态初始化之前,应执行静态初始化.