Frage

Wenn eine Variable als static in einer Funktion Gültigkeitsbereich deklariert wird, wird es nur einmal initialisiert und behält ihren Wert zwischen Funktionsaufrufen. Was genau ist seine Lebensdauer? Wenn Sie den Konstruktor und Destruktor aufgerufen werden?

void foo() 
{ 
    static string plonk = "When will I die?";
}
War es hilfreich?

Lösung

Die Lebensdauer der Funktion static Variablen beginnt das erste Mal [0] der Programmablauf trifft auf die Erklärung und endet bei Programmende. Dies bedeutet, dass die Laufzeit einig Buchhaltung in ausführen muss, um es zu zerstören, nur wenn es tatsächlich gebaut wurde.

Darüber hinaus, da der Standard sagt, dass die Destruktoren von statischen Objekten in der umgekehrten Reihenfolge des Bauabschluss ausgeführt werden muss [1] , und die Reihenfolge des Bau auf dem spezifischen Programmablauf abhängen muss die Reihenfolge der Konstruktion berücksichtigt werden.

Beispiel:

struct emitter {
    string str;
    emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
    ~emitter() { cout << "Destroyed " << str << endl; }
};

void foo(bool skip_first) 
{
    if (!skip_first)
        static emitter a("in if");
    static emitter b("in foo");
}

int main(int argc, char*[])
{
    foo(argc != 2);
    if (argc == 3)
        foo(false);
}

Ausgang:

  

C:> sample.exe
  Erstellt in foo
  Zerstört in foo

     

C:> sample.exe 1 |   Erstellt in wenn
  Erstellt in foo
  Zerstört in foo
  Zerstört, wenn

     

C:> sample.exe 1 2
  Erstellt in foo
  Erstellt in wenn
  Zerstört, wenn
  Zerstört in foo

[0] Da 98 C ++ [2] hat keinen Hinweis auf mehrere Threads, wie dies in einer Multi-Thread-Umgebung verhalten wird nicht spezifiziert ist, und kann problematisch sein, wie Roddy erwähnt.

[1] C ++ 98 3.6.3.1 [basic.start.term]

[2] In C ++ 11 Statik werden in einem Thread sichere Weise initialisiert, dies ist auch bekannt als Magie Statiken .

Andere Tipps

Motti ist rechts über die Reihenfolge, aber es gibt einige andere Dinge zu beachten:

Compiler verwendet in der Regel eine versteckte Flagvariable, um anzuzeigen, wenn die lokale Statik bereits initialisiert wurde, und dieser Flag auf jedem Eintrag in die Funktion aktiviert ist. Offensichtlich ist dies eine kleine Performance-Einbußen, aber was ist mehr ein Anliegen ist, dass dieser Flag nicht Thread-sicher sein, ist gewährleistet.

Wenn Sie eine lokale statische haben wie oben und foo von mehreren Threads aufgerufen wird, können Sie Rennbedingungen haben verursacht plonk falsch oder sogar mehrmals initialisiert werden. Auch in diesem Fall plonk kann von einem anderen Thread als der destructed bekommen, die sie aufgebaut ist.

Trotz allem, was die Norm sagt, würde ich von der tatsächlichen Reihenfolge der lokalen statischer Zerstörung sehr vorsichtig sein, weil es möglich ist, dass Sie unwissentlich auf einem statisches Wesen noch gültig verlassen können, nachdem es zerstört worden ist, und das ist wirklich schwierig zu verfolgen Nieder.

Die bestehenden Erklärungen sind nicht wirklich vollständig ohne die eigentliche Regel aus dem in 6.7 gefunden Standard:

  

Die Null-Initialisierung alle Block-scope Variablen mit statischer Lagerdauer oder Fadenspeicherdauer durchgeführt wird, bevor eine andere Initialisierung stattfindet. Konstante Initialisierung einer Block-scope Entität mit statischer Lagerdauer ggf. durchgeführt wird, bevor sein erster Block eingegeben wird. Eine Implementierung erlaubt frühe Initialisierung von anderem Block-scope Variablen mit statischer oder Fadenlagerdauer unter den gleichen Bedingungen durchzuführen, dass eine Implementierung statisch zulässig ist eine Variable mit statischer oder Fadenspeicherdauer in Namespacebereich zu initialisieren. Andernfalls wird eine solche Variable ist das erste Mal initialisiert Steuerung durch ihre Erklärung übergibt; Eine solche Variable betrachtet bei Beendigung seiner Initialisierung initialisiert wird. Wenn die Initialisierung beendet durch das Auslösen einer Ausnahme, die Initialisierung   wird versucht nicht abgeschlossen ist, so wieder das nächste Mal Kontrolle ins Spiel kommt die Erklärung. Wenn die Steuerung die Deklaration gleichzeitig eintritt, während die Variable initialisiert wird, so wird die gleichzeitige Ausführung für den Abschluß der Initialisierung warten. Wenn die Kontrolle der Erklärung tritt wieder rekursiv, während die Variable initialisiert wird, ist das Verhalten nicht definiert.

FWIW, CodeGear C ++ Builder Destruct nicht in der erwarteten Reihenfolge nach dem Standard.

C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if

... und das ist ein weiterer Grund für die Zerstörung, um nicht zu verlassen!

Die Statische Variablen ist ins Spiel kommen, wenn die Programmausführung startet und es verfügbar bleiben, bis die Programmausführung endet.

Die statischen Variablen werden in dem Datensegment des Speichers erstellt .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top