Ich glaube, mein Problem am besten in Code beschrieben:C++ globale Initialisierungsreihenfolge ignoriert Abhängigkeiten?
#include <stdio.h>
struct Foo;
extern Foo globalFoo;
struct Foo {
Foo() {
printf("Foo::Foo()\n");
}
void add() {
printf("Foo::add()\n");
}
static int addToGlobal() {
printf("Foo::addToGlobal() START\n");
globalFoo.add();
printf("Foo::addToGlobal() END\n");
return 0;
}
};
Foo globalFoo;
int dummy = Foo::addToGlobal();
int main() {
printf("main()\n");
return 0;
}
Die obigen Drucke (mit gcc 4.4.3):
Foo::Foo()
Foo::addToGlobal() START
Foo::add()
Foo::addToGlobal() END
main()
Das ist, was ich erwarte, und scheint logisch.
Allerdings, wenn ich die folgenden Zeilen tauschen:
Foo globalFoo;
int dummy = Foo::addToGlobal();
in diese:
int dummy = Foo::addToGlobal();
Foo globalFoo;
gibt das Programm die folgenden:
Foo::addToGlobal() START
Foo::add()
Foo::addToGlobal() END
Foo::Foo()
main()
Es scheint Instanzmethoden Foo
werden mit einer noch nicht vorhandenen Instanz aufgerufen wurde gebaut! Etwas so Einfaches wie das Verschieben der Deklaration einer Variablen in den globalen Gültigkeitsbereich beeinflusst das Verhalten des Programms, und das lässt mich glauben, dass (1) die Reihenfolge der Initialisierung von Globals nicht definiert ist und (2) die Reihenfolge der Initialisierung von Globals ignoriert alle Abhängigkeiten. Ist das richtig? Kann sichergestellt werden, dass der Konstruktor Foo
vor der Initialisierung dummy
aufgerufen wird?
Das Problem, das ich zu lösen versuche, füllt ein Repository von Elementen (eine statische Instanz von Foo
) statisch. In meinem aktuellen Versuch verwende ich ein Makro, das (unter anderem) eine globale Variable (in einem anonymen Namensraum, um Namenskonflikte zu vermeiden) erstellt, deren Initialisierung die statische Initialisierung auslöst. Vielleicht gehe ich mein Problem aus dem falschen Blickwinkel an? Gibt es eine bessere Alternative (n)? Vielen Dank.
Ich bin auf diese Lösung gestoßen, nachdem ich meine Frage gepostet habe. Ich habe es versucht und es scheint zu funktionieren. Es kann jedoch ein Problem geben: Gibt es mehrere Instanzen aufgrund von 'statischem' innerhalb von 'Singleton'? Das heißt, könnte 'Foo :: singleton()' möglicherweise unterschiedliche Dinge zurückgeben, wenn es in einer Header-Datei deklariert und definiert ist und über verschiedene Übersetzungseinheiten hinweg enthalten ist? – strager
Ein weiteres mögliches Problem mit diesem Muster ist, dass es AFAIK nicht sicher ist, gleichzeitig auf Singleton zuzugreifen. – FuleSnabel
@strager: Wenn die lokale Variable 'static' deklariert wird, dann wird es eine einzelne Instanz davon geben, selbst wenn die Funktion inline ist (das heißt, separat in verschiedenen Übersetzungseinheiten kompiliert), muss der Linker sicherstellen, dass nur eine einzige Definition von Die Variable existiert. –