c ++ одиночный порядок инициализации - PullRequest
3 голосов
/ 17 февраля 2010

у меня

class Foo
class Bar

Теперь я хочу

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

для инициализации до

int main()

называется.

Кроме того, я хочу

Foo::singleton

для инициализации до

Bar::singleton

Могу ли я в этом убедиться?

Спасибо!

Ответы [ 4 ]

3 голосов
/ 17 февраля 2010

Глобальные переменные (например, синглтоны), определенные в одной и той же единице перевода, инициализируются в том порядке, в котором они определены. Поэтому поместите определение обоих синглетонов в один и тот же исходный файл в правильном порядке.

Если они будут определены в разных исходных файлах, порядок их инициализации не будет указан (« статический порядок инициализации fiasco »).

2 голосов
/ 17 февраля 2010

См. Также Порядок инициализации статических переменных

Для 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
  ...
}

Помните, что с выходом из программы все будет так же ужасно с одиночками, поэтому часто лучше сделать это явным.

0 голосов
/ 17 февраля 2010

В двух словах:

// 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 голосов
/ 17 февраля 2010
#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()
...