Wann werden statische Variablen auf Funktionsebene zugewiesen/initialisiert?

StackOverflow https://stackoverflow.com/questions/55510

  •  09-06-2019
  •  | 
  •  

Frage

Ich bin ziemlich sicher, dass global deklarierte Variablen beim Programmstart zugewiesen (und ggf. initialisiert) werden.

int globalgarbage;
unsigned int anumber = 42;

Aber was ist mit statischen, die innerhalb einer Funktion definiert sind?

void doSomething()
{
  static bool globalish = true;
  // ...
}

Wann ist der Platz für globalish zugeteilt?Ich schätze, wann das Programm startet.Aber wird es dann auch initialisiert?Oder wird es wann initialisiert? doSomething() wird zuerst aufgerufen?

War es hilfreich?

Lösung

Ich war neugierig auf diese so schrieb ich folgendes Testprogramm und kompiliert es mit g ++ Version 4.1.2.

include <iostream>
#include <string>

using namespace std;

class test
{
public:
        test(const char *name)
                : _name(name)
        {
                cout << _name << " created" << endl;
        }

        ~test()
        {
                cout << _name << " destroyed" << endl;
        }

        string _name;
};

test t("global variable");

void f()
{
        static test t("static variable");

        test t2("Local variable");

        cout << "Function executed" << endl;
}


int main()
{
        test t("local to main");

        cout << "Program start" << endl;

        f();

        cout << "Program end" << endl;
        return 0;
}

Die Ergebnisse waren nicht das, was ich erwartet hatte. Der Konstruktor für das statische Objekt wurde nicht bis zum ersten Mal der Funktion aufgerufen aufgerufen wurde. Hier ist die Ausgabe:

global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed

Andere Tipps

Einige relevante Wortschwall aus C ++ Standard:

  

3.6.2 Initialisierung nicht lokaler Objekte [basic.start.init]

     

1

     

Der Speicher für Objekte mit statischen Speicher   Dauer ( basic.stc.static ) beträgt Null initialisiert ( dcl.init )   vor jeder anderen Initialisierung erfolgt. Objekte   POD-Typen ( basic.types ) mit statischer Speicherdauer   mit konstanten Ausdrücken initialisiert ( expr.const ) beträgt   initialisiert, bevor eine dynamische Initialisierung stattfindet.   Objekte Namespacebereich mit statischer Speicherdauer definiert in   die gleiche Einheit Übersetzung und dynamisch initialisiert wird sein   in der Reihenfolge, in der initialisiert ihre Definition erscheint in   die Übersetzungseinheit. [Anmerkung: dcl.init.aggr beschreibt die   Reihenfolge, in der Aggregat-Mitglieder initialisiert. Das   Initialisierung lokaler statischer Objekte in stmt.dcl beschrieben. ]

     

[mehr Text mehr Freiheiten für Compiler Schriftsteller Hinzufügen]

     

6.7 Erklärung Anweisung [stmt.dcl]

     

...

     

4

     

Die Null-Initialisierung ( dcl.init ) alle lokalen Objekte mit   statische Speicherdauer ( basic.stc.static ) wird vor   andere Initialisierung erfolgt. Eine lokale Aufgabe   POD-Typ ( basic.types ) mit statischer Speicherdauer   initialisiert mit konstantem Ausdrücke initialisiert vor seinem   Block wird zuerst eingegeben. Eine Implementierung erlaubt auszuführen   Anfang Initialisierung von anderen lokalen Objekte mit statischen Speicher   Dauer unter den gleichen Bedingungen, dass eine Implementierung ist   gestattet statisch ein Objekt mit statischen Speicher zu initialisieren   Dauer in Namespacebereich ( basic.start.init ). ansonsten solche   Eine Aufgabe ist das erste Mal initialisiert Steuerung durchläuft seinen   Erklärung; Ein solches Objekt betrachtet von der initialisiert wird   Abschluss seiner Initialisierung. Wenn die Initialisierung beendet durch   eine Ausnahme zu werfen, ist die Initialisierung nicht abgeschlossen ist, so wird es   versucht werden, wieder das nächste Mal, Kontrolle der Erklärung eintritt. Wenn die Steuerung wieder in die Deklaration (rekursiv), während das Objekt zu sein, ist   initialisiert, ist das Verhalten nicht definiert. [ Beispiel:

      int foo(int i)
      {
          static int s = foo(2*i);  // recursive call - undefined
          return i+1;
      }
     

- Ende Beispiel ]

     

5

     

Der Destruktor für ein lokales Objekt mit statischer Speicherdauer wird   ausgeführt werden, wenn und nur wenn der Variable konstruiert.   [Anmerkung: basic.start.term beschreibt die Reihenfolge, in der lokalen   Objekte mit statischer Speicherdauer werden zerstört. ]

Der Speicher für alle statischen Variablen beim Programmlast zugeordnet. Aber lokale statische Variablen erstellt und initialisiert das erste Mal, wenn sie verwendet wird, nicht beim Programmstart. Es gibt einige gute Lektüre über das, und Statik in der Regel hier . Generell denke ich, einige dieser Probleme bei der Umsetzung abhängen, vor allem, wenn Sie, wo im Speicher wissen wollen diese Sachen befinden werden.

Der Compiler statischen Variable (n) zuweisen in einer Funktion foo bei Programm Last definiert, aber der Compiler fügt auch einige zusätzliche Anweisungen (Maschinencode), um Ihre Funktion foo, so dass das erste Mal, dass dieser zusätzliche Code aufgerufen wird, initialisieren der statischen variablen (zB den Konstruktor aufruft, wo zutreffend).

@ Adam:. Diese hinter den Kulissen Injektion von Code durch den Compiler ist der Grund für das Ergebnis, das Sie sah

Ich versuche, wieder zu testen Code von Adam Pierce und fügte zwei weitere Fälle: statische Variable in der Klasse und POD-Typ. Mein Compiler g ++ 4.8.1 unter Windows OS (MinGW-32). Das Ergebnis wird statischer Variable in der Klasse wird mit demselben globalen Variablen behandelt. Der Konstruktor wird aufgerufen werden, bevor Hauptfunktion eingegeben werden.

  • Schlussfolgerung (für g ++, Windows-Umgebung):

    1. Globale Variable und statisches Element in der Klasse : Konstruktor vor eingeben main aufgerufen wird Funktion (1) .
    2. Lokale statische Variable :. Konstruktor nur aufgerufen wird, wenn die Ausführung seiner Erklärung zum ersten Mal erreicht
    3. Wenn Lokale statische Variable ist der Typ POD , dann wird es auch vor Eingabe Haupt Funktion initialisiert (1) . Beispiel für POD-Typ: static int number = 10;

(1) : Der richtige Zustand sein sollte. "bevor eine Funktion aus der gleichen Übersetzungseinheit werden als" jedoch für einfache, wie im Beispiel unten, dann ist es main Funktion.

schließen

#include < string>

using namespace std;

class test
{
public:
   test(const char *name)
            : _name(name)
    {
            cout << _name << " created" << endl;
    }

    ~test()
    {
            cout << _name << " destroyed" << endl;
    }

    string _name;
    static test t; // static member
 };
test test::t("static in class");

test t("global variable");

void f()
{
    static  test t("static variable");
    static int num = 10 ; // POD type, init before enter main function

    test t2("Local variable");
    cout << "Function executed" << endl;
}

int main()
{
    test t("local to main");
    cout << "Program start" << endl;
    f();
    cout << "Program end" << endl;
    return 0;
 }

Ergebnis:

static in class created
global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed
static in class destroyed

Wer in Linux env getestet?

Statische Variablen sind in einem Code-Segment zugeordnet -. Sie sind Teil des ausführbaren Bildes sind, und so abgebildet werden, in bereits initialisiert

Statische Variablen innerhalb Funktionsumfang werden gleich behandelt, die Scoping ist eine reine Sprachniveau Konstrukt.

Aus diesem Grunde werden Sie garantiert, dass eine statische Variable wird auf 0 initialisiert werden, anstatt einen nicht definierten Wert (es sei denn, Sie etwas anderes angeben).

Es gibt einige andere Facetten der Initialisierung Sie die Vorteile aus nehmen können -. Für die Segmente Beispiel geteilt erlauben verschiedene Instanzen die ausführbare Datei ausgeführt wird auf einmal die gleichen statischen Variablen zugreifen

In C ++ (scoped global) statische Objekte haben ihre Erbauer genannt als Teil des Programms starten, unter der Kontrolle der C-Laufzeitbibliothek. Unter Visual C ++ zumindest die Reihenfolge, dass Objekte, die von der init_seg Pragma.

  

Oder ist es initialisiert, wenn doSomething () aufgerufen wird zuerst?

Ja, es ist. Dies unter anderem, können Sie initialisieren global zugegriffen Datenstrukturen, wenn es angebracht ist, zum Beispiel innerhalb try / catch-Blöcke. Z.B. anstelle von

int foo = init(); // bad if init() throws something

int main() {
  try {
    ...
  }
  catch(...){
    ...
  }
}

Sie können schreiben

int& foo() {
  static int myfoo = init();
  return myfoo;
}

und verwenden Sie es innerhalb des try / catch-Block. Beim ersten Aufruf wird die Variable initialisiert. Dann wird auf dem ersten und die nächsten Anruf, wird sein Wert (Referenz) zurückgeführt werden.

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