C++ 单例模式初始化顺序

3

我有

class Foo
class Bar

Now, I want

Foo* Foo::singleton = new Foo();
Bar* Bar::singleton = new Bar();

在进行初始化之前,需要执行以下操作:

int main()

被称为。

此外,我希望

Foo::singleton

在初始化之前

Bar::singleton

有什么方法可以确保这一点吗?
谢谢!
4个回答

4

在同一翻译单元中定义的全局变量(如单例)按照定义顺序进行初始化。因此,请将两个单例的定义放在同一个源文件中,并按正确顺序进行。

如果它们在不同的源文件中定义,则初始化顺序是未指定的(即“静态初始化顺序惨案”)。


2
请参阅静态变量初始化顺序 对于gcc使用init_priority: http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html 可在不同的翻译单元之间工作。因此,您的代码应该这样写:
Foo* Foo::singleton __attribute__ ((init_priority (2000))) = new Foo();
Bar* Bar::singleton __attribute__ ((init_priority (3000))) = new Bar();

我现在没有gcc,所以无法验证这一点,但我以前使用过它。另一个更简单、更可移植的解决方案是避免静态初始化,在main函数中某个明确定义的位置显式地按顺序创建单例。

// Nothing in static area

void main(void)
{
  // Init singletons in explicit order
  {
    Foo* Foo::singleton = new Foo();
    Bar* Bar::singleton = new Bar();
  }

  // Start program execution
  ...
}

记住,离开程序时单例模式也会变得非常混乱,因此明确声明会更好。


1
简而言之:
// smooth.cpp
#include "foo.h"
#include "bar.h"

Foo* Foo::singleton = new Foo();
Bar* Bar::singleton = new Bar();

一个不错的语法,可以避免担心这个问题:
Foo& Foo::singleton()
{
  static Foo Singleton;
  return Singleton;
}

这种语法的好处在于,在第一次调用该方法时就会初始化单例,因此当访问它的方法时通常不必担心它何时发生,因为无论如何你都可以获得它 :)

0
#include <iostream>

class Foo {
public:
  static Foo *singleton ()
  {
    if (foo == NULL)
      foo = new Foo;
    return foo;
  }
private:
  Foo ()
  {
    std::cout << "Foo()\n";
  }
  static Foo *foo;
};

Foo *Foo::foo = NULL;

Foo *singleton = Foo::singleton ();

int
main ()
{
  std::cout << "main()\n";
  return 0;
}

输出:

Foo()
main()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接