views:

185

answers:

4

I have

class Foo
class Bar

Now, I want

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

to both initialize before

int main()

is called.

Furthermore, I want

Foo::singleton

to initialize before

Bar::singleton

Is there anyway I can ensure that?

Thanks!

+3  A: 

Global variables (like the singletons) that are defined in the same translation unit are initialized in the order in which they are defined. So put the definition of both singletons in the same source file, in the correct order.

If they would be defined in different source files the order in which they are initialized would be unspecified (the "static initialization order fiasco").

sth
A: 
#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;
}

Output:

Foo()
main()
Vijay Mathew
+1  A: 

See also http://stackoverflow.com/questions/211237/c-static-variables-initialisation-order

For gcc use init_priority:

http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html

Works across different translation units. So your code would read:

Foo* Foo::singleton __attribute__ ((init_priority (2000))) = new Foo();
Bar* Bar::singleton __attribute__ ((init_priority (3000))) = new Bar();

I don't have gcc handy right now so I can't verify this, but I have used it before. The other simpler and more portable solution is to avoid static initialization, and explicitly create the singletons in order at some well defined place within 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
  ...
}

Remember, things will get just as gnarly with singletons on the way out of the program as well, so its often better to make it explicit.

Justicle
A: 

In a nutshell:

// smooth.cpp
#include "foo.h"
#include "bar.h"

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

A nice syntax, to avoid worrying about that:

Foo& Foo::singleton()
{
  static Foo Singleton;
  return Singleton;
}

The good thing about this syntax, is that the singleton is initialized at the first call of the method, thus you don't have to worry (usually) when it happens, since when calling the method to access it you get it anyway :)

Matthieu M.