Frage

Wenn ich statische Variablen in C ++ verwenden, ich oft am Ende wollen eine Variable mit einem anderen an den Konstruktor zu initialisieren. Mit anderen Worten, ich möchte statische Instanzen erstellen, die voneinander abhängig sind.

Innerhalb eines CPP oder .h-Datei ist dies kein Problem: die Instanzen werden in der Reihenfolge erstellt sie deklariert sind. Wenn Sie jedoch eine statische Instanz mit einer Instanz in einer anderen Übersetzungseinheit initialisiert werden sollen, scheint die Reihenfolge unmöglich zu spezifizieren. Das Ergebnis ist, dass, je nach Wetterlage kann es vorkommen, dass die Instanz, die von einem anderen abhängt aufgebaut wird, und erst danach die andere Instanz aufgebaut ist. Das Ergebnis ist, dass die erste Instanz falsch initialisiert wird.

Wer weiß, wie um sicherzustellen, dass statische Objekte in der richtigen Reihenfolge erstellt werden? Ich habe eine lange Zeit für eine Lösung gesucht, die alle von ihnen (einschließlich des Schwarz Zähler Lösung) versucht, aber ich beginne zu zweifeln, es ist eines, das wirklich funktioniert.

Eine Möglichkeit ist der Trick mit dem statischen Funktionselement:

Type& globalObject()
{
    static Type theOneAndOnlyInstance;
    return theOneAndOnlyInstance;
}

Tatsächlich funktionierts. Leider haben Sie globalObject (). MemberFunction () statt globalObject.MemberFunction (), was etwas verwirrend und unelegant Client-Code.

schreiben

Update: Vielen Dank für Ihre Reaktionen. Leider scheint es in der Tat, wie ich meine eigene Frage beantwortet haben. Ich denke, ich werde lernen müssen, damit zu leben ...

War es hilfreich?

Lösung

Sie haben Ihre eigene Frage beantwortet. Statische Initialisierungsreihenfolge ist nicht definiert, und die eleganteste Weise um sie (während noch statische Initialisierung zu tun heißt Refactoring es nicht ganz weg) wird die Initialisierung in einer Funktion zu wickeln.

Lesen Sie die C ++ FAQ Artikel ab https://isocpp.org/wiki / faq / ctors # static-init-Ordnung

Andere Tipps

Vielleicht sollten Sie überlegen, ob Sie so viele globale statische Variablen benötigen. Während sie manchmal nützlich sein kann, oft ist es viel einfacher, sie zu einem kleineren lokalen Bereich Refactoring, vor allem, wenn Sie feststellen, dass einige statischen Variablen von anderen abhängig.

Aber du hast Recht, es gibt keine Möglichkeit, eine bestimmte Reihenfolge der Initialisierung zu gewährleisten, und so, wenn Sie Ihr Herz auf sie gesetzt wird, die Initialisierung in Abhängigkeit zu halten, wie Sie erwähnt haben, ist wahrscheinlich der einfachste Weg.

  

Tatsächlich funktionierts. Leider haben Sie globalObject (). MemberFunction () statt globalObject.MemberFunction (), was etwas verwirrend und unelegant Client-Code.

schreiben

Aber das Wichtigste ist, dass es funktioniert, und dass es Ausfall sicher, dh. es ist nicht einfach, die richtige Anwendung zu umgehen.

Programm Korrektheit sollte Ihre erste Priorität sein. Auch IMHO, die () oben ist rein stilistisch - dh. völlig unwichtig.

Abhängig von Ihrer Plattform, vorsichtig sein, zu viel dynamischer Initialisierung. Es ist eine relativ kleine Menge an aufzuräumen, den Platz für dynamischen initializers nehmen kann (siehe hier ). Sie können dieses Problem lösen, ein globales Objekt Container mit, die Mitglieder unterschiedliche globale Objekte enthält. Sie haben daher:

Globals & getGlobals ()
{
  static Globals cache;
  return cache;
}

Es gibt nur einen Anruf zu ~ Globals (), um für alle globalen Objekte in Ihrem Programm zu bereinigen. Um einen globalen zu Zugriff auf Sie haben noch so etwas wie:

getGlobals().configuration.memberFunction ();

Wenn Sie wirklich wollten Sie dies in einem Makro wickeln könnte ein klein wenig Tipparbeit zu sparen mit einem Makro:

#define GLOBAL(X) getGlobals().#X
GLOBAL(object).memberFunction ();

Obwohl dies auf Ihre erste Lösung nur syntaktischer Zucker ist.

bei einem Verfahren der statischen Wrapping des Auftrag Problem zu beheben, aber es ist Thread nicht sicher, wie andere darauf hingewiesen haben, aber Sie können dies tun, um auch sie fädeln zu machen, ob das ein Anliegen ist.

// File scope static pointer is thread safe and is initialized first.
static Type * theOneAndOnlyInstance = 0;

Type& globalObject()
{
    if(theOneAndOnlyInstance == 0)
    {
         // Put mutex lock here for thread safety
         theOneAndOnlyInstance = new Type();
    }

    return *theOneAndOnlyInstance;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top