2010-02-17 12 views
3

J'aiC++ singleton ordre d'initialisation

class Foo 
class Bar 

Maintenant, je veux

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

à la fois avant initialize

int main() 

est appelé.

De plus, je veux

Foo::singleton 

à initialize avant

Bar::singleton 

Est-il de toute façon je peux assurer que?

Merci!

Répondre

2

Voir aussi Static variables initialisation order

Pour une utilisation gcc init_priority:

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

Works à travers différentes unités de traduction. Donc, votre code serait:

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

Je ne je peux pas juste avoir à portée de main gcc maintenant afin de ne pas vérifier, mais je l'ai utilisé auparavant. L'autre solution plus simple et plus portable est d'éviter l'initialisation statique et de créer explicitement les singletons dans l'ordre à un endroit bien défini dans 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 
    ... 
} 

Rappelez-vous, les choses vont se noueux comme avec singletons sur la sortie du programme aussi bien, il est donc souvent préférable de le rendre explicite.

3

Les variables globales (comme les singletons) qui sont définies dans la même unité de traduction sont initialisées dans l'ordre dans lequel elles sont définies. Mettez donc la définition des deux singletons dans le même fichier source, dans le bon ordre.

Si elles étaient définies dans différents fichiers source, l'ordre dans lequel elles sont initialisées serait non spécifié (le "static initialization order fiasco").

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; 
} 

Sortie:

Foo() 
main() 
0

En bref:

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

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

Une syntaxe agréable, pour éviter se soucier que:

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

La bonne chose au sujet de cette syntaxe, est que le singleton est initialisé au premier appel de la méthode, donc vous n'avez pas à vous inquiéter (en général) quand cela arrive, car lorsque vous appelez la méthode pour y accéder, vous l'obtenez quand même :)