2013-07-23 20 views
9

Ich habe mehrere Beiträge auf C++ Initialisierung von Google gelesen, von denen einige mich hier auf StackOverflow leiten. Die Konzepte I aus diesen Pfosten aufgenommen sind, wie folgt:Null Initialisierung und statische Initialisierung des lokalen Bereichs statische Variable

  • Die Reihenfolge der Initialisierung von C++ ist:
    1. Null Initialization;
    2. Statische Initialisierung;
    3. Dynamische Initialisierung.
  • Statische Objekte (Variablen enthalten) sind erste Null initialisierten und dann Static-initialisierten.

Ich habe mehrere Anfragen in Bezug auf die Initialisierung Ausgabe (Speicherklasse Problem kann auch in Beziehung gesetzt werden):

  • Globale Objekte (definiert ohne statische Schlüsselwort) sind auch statische Objekte, oder?
  • Globale Objekte sind auch initialisiert wie statische Objekte durch zwei Schritte wie oben, oder?
  • Was ist die Statische Initialisierung? Bezieht es sich auf die Initialisierung statischer Objekte (definiert mit statisch Schlüsselwort)?
  • Ich lese auch, dass Objekte innerhalb Block definiert (d. H. In einer Funktion) mit statische Schlüsselwort wird initialisiert, wenn der Ausführungs-Thread zuerst den Block betritt! Das bedeutet, dass lokale statische Objekte nicht initialisiert werden, bevor Haupt Funktionsausführung. Dies bedeutet, dass sie nicht als die beiden oben genannten Schritte initialisiert werden, oder?
  • Dynamische Initialisierung bezieht sich auf die Initialisierung von Objekten erstellt von neue Operator, richtig? Es könnte beziehen sich auf die Initialisierung wie myClass obj = myClass(100); oder myClass obj = foo();

Ich habe zu viele Anfragen auf der Initialisierung und Speicherklassen-Bezeichner Fragen. Ich lese das C++ 2003 Standard Dokument, kann aber keine klare Logik finden, da sie im gesamten Dokument verstreut sind.

Ich hoffe, Sie geben mir eine Antwort, die logisch erklärt die gesamte Karte der Speicherklasse Spezifizierer und Initialisierung. Jede Referenz ist willkommen!

Code, der meine Frage erklären könnte:

class myClass{ 
public: 
    int i; 
    myClass(int j = 10): j(i){} 
    // other declarations 
}; 

myClass obj1;//global scope 
static myClass obj2(2);//file scope 
{ //local scope 
    myClass obj3(3); 
    static myClass obj4(4); 
} 

EDIT:
Wenn Sie meine Frage denken, ziemlich langweilig ist, können Sie Ihre Ideen helfen zu erklären, oben basierend auf dem Code.

+0

Dieser Beitrag könnte nützlich sein: http://bytes.com/topic/c/answers/860211-global-variable-static-global-variable –

Antwort

18

Ich las einige Beiträge über C++ Initialisierung von Google, von denen einige mich auf Stackoverflow hier lenken. Die Konzepte I aus diesen Pfosten aufgenommen sind, wie folgt:

  • Die Reihenfolge der Initialisierung von C++ ist:
    1. Null Initialization;
    2. Statische Initialisierung;
    3. Dynamische Initialisierung.

Ja, in der Tat gibt es drei Phasen (im Standard). Lassen Sie uns sie klären, bevor Sie fortfahren:

  • Null Initialisierung: Der Speicher ist mit 0s auf Byte-Ebene gefüllt.
  • Constant Initialisierung: a vorausberechneten (Kompilierung-) Bytemuster an der Speicherstelle des Objekts kopiert
  • statische Initialisierung: Null Initialisierung durch Constant Initialization gefolgt
  • Dynamische Initialisierung: eine Funktion ausgeführt wird, initialisieren der Speicher
  • Ein einfaches Beispiel:

    int const i = 5;  // static initialization 
    int const j = foo(); // dynamic initialization 
    
    • Statische Objekte (Variablen enthalten) werden zuerst Null initialisiert und dann Statisch-initialisiert.

    Ja und nein.

    Die Norm schreibt vor, dass die Objekte Null initialisiert und dann die erste sein, sie sind:

    • Konstante initialisiert, wenn möglich
    • dynamisch ansonsten initialisiert (der Compiler nicht den Speicherinhalt zur Compile-Zeit berechnen können)
    • Hinweis: Im Falle einer konstanten Initialisierung kann der Compiler nach der as-if-Regel den ersten Null-initialisierten Speicher weglassen.

      Ich habe mehrere Anfragen in Bezug auf die Initialisierung Ausgabe (Speicherklasse Problem kann auch in Beziehung gesetzt werden):

      • Globale Objekte (definiert ohne statische Schlüsselwort) sind auch statische Objekte, oder?

      Ja, in Dateigültigkeitsbereich der static Objekt ist nur über die Sichtbarkeit des Symbols. Auf ein globales Objekt kann namentlich aus einer anderen Quelldatei verwiesen werden, während ein static Objektname vollständig lokal für die aktuelle Quelldatei ist.

      Die Verwirrung rührt von der Wiederverwendung der Welt static in vielen verschiedenen Situationen :(

      • globale Objekte sind ebenfalls wie oben durch zwei Schritte wie statische Objekte initialisiert, nicht wahr?

      Ja, genau wie lokale statische Objekte

      • Was ist die Statische Initialisierung? Bezieht es sich auf die Initialisierung statischer Objekte (definiert mit statisch Schlüsselwort)?

      Nein, wie oben erläutert, bezieht sich Objekte ohne Ausführung einer benutzerdefinierten Funktion sondern Kopieren einer im Voraus berechneten Byte-Muster über den Objektspeicher zu initialisieren. Beachten Sie, dass bei Objekten, die später dynamisch initialisiert werden, nur der Speicher auf Null gesetzt wird.

      • I auch gelesen, dass im Block (d.h. in einer Funktion) mit statischem Schlüsselwort definierten Objekte initialisiert wird, wenn der Ausführungs-Thread den Block zuerst eintritt! Das bedeutet, dass lokale statische Objekte nicht initialisiert werden, bevor Haupt Funktionsausführung. Dies bedeutet, dass sie nicht als die beiden oben genannten Schritte initialisiert werden, oder?

      Sie sind mit dem Prozess in zwei Schritten initialisiert, obwohl in der Tat nur die erste Ausführungszeit durch ihre Definition übergeben. Der Prozess ist also der gleiche, aber das Timing ist subtil anders.

      In der Praxis jedoch, wenn ihre Initialisierung statisch ist (dh das Speichermuster ist ein Kompilierzeitmuster) und ihre Adresse nicht genommen wird, können sie weg optimiert werden.

      Beachten Sie, dass bei einer dynamischen Initialisierung bei fehlgeschlagener Initialisierung (eine Ausnahme wird von der Funktion ausgelöst, die sie initialisieren soll) erneut versucht wird, wenn die Flow-Steuerung das nächste Mal ihre Definition durchläuft.

      • Dynamische Initialisierung bezieht sich auf die Initialisierung von Objekten durch neue Betreiber erstellt wurden, nicht wahr? Es mag wie myClass obj = myClass(100); der Initialisierung beziehen oder myClass obj = foo();

      Keineswegs, bezieht er sich auf die Initialisierung der Ausführung einer benutzerdefinierten Funktion erfordert (Anmerkung: std::string hat einen benutzerdefinierten Konstruktor so weit wie die Sprache C++ ist besorgt).

      EDIT: Mein Dank an Zach, der auf mich zeigte Ich nannte fälschlicherweise Static Initialization, was der C++ 11 Standard Constant Initialization nennt; Dieser Fehler sollte jetzt behoben sein.

    +0

    Matthieu, deine Erklärung ist tödlich nützlich. Globale oder statische Objekte (lokal oder nicht) werden zuerst zur Kompilierzeit (Verknüpfungsstufe) ** initialisiert und dann zur Kompilierzeit ** statisch initialisiert oder zur Ladezeit dynamisch initialisiert ** (kurz zuvor Hauptfunktion). – Zachary

    +0

    In Ihrem Beispiel sind sie zwei ganze Zahlen. Also was wenn zwei Objekte. Zum Beispiel wie in meinem Code 'myClass obj1; myClass obj2 = MeineKlasse (10); myClass obj3 (20); myClass obj4 = foo(); '. Benötigen diese Objekte alle eine dynamische Initialisierung oder statische Initialisierung beim 2. Initialisierungsschritt? – Zachary

    +0

    @Zack: Sie würden normalerweise dynamische Initialisierung benötigen, aber der Compiler darf dies durch statische Initialisierung unter den Als-Wenn-Regeln ersetzen, wenn es beweisen kann, dass Sie die Änderung nicht bemerken. –

    -4

    Ich glaube, es gibt drei verschiedene Konzepte: Initialisierung der Variablen, die Position der Variablen im Speicher, die Zeit, die die Variable initialisiert wird.

    Erstens: Die Initialisierung

    Wenn eine Variable im Speicher zugeordnet ist, typische Prozessoren lassen die Erinnerung unangetastet, so wird die Variable den gleichen Wert haben, dass jemand anderes zuvor gespeichert. Aus Sicherheitsgründen fügen einige Compiler den zusätzlichen Code hinzu, um alle Variablen zu initialisieren, die sie auf Null setzen. Ich denke, das ist, was Sie mit "Zero Initialization" meinen. Es passiert, wenn Sie sagen:

    int i; // not all compilers set this to zero 
    

    Allerdings, wenn Sie an den Compiler sagen:

    int i = 10; 
    

    dann der Compiler weist den Prozessor 10 in dem Speicher abgelegt werden soll, anstatt sie mit alten Werten zu verlassen oder Einstellung bis Null. Ich denke, das ist es, was Sie mit "Statische Initialisierung" meinen.

    Schließlich könnte man sagen:

    int i; 
    ... 
    ... 
    i = 11; 
    

    dann der Prozessor „Null initialisiert“ (oder verlässt den alten Wert), wenn int i; dann ausgeführt wird, wenn er die Linie erreicht i = 11 es „initialisiert dynamisch“ die Variable 11 (das ist sehr lange nach der ersten Initialisierung passieren kann

    Zweitens:. Lage des variablen

    Es gibt: Stack-basierte Variablen (manchmal statische Variablen genannt) und mem ory-heap-Variablen (manchmal dynamische Variablen genannt).

    int i; 
    

    oder den Speicherheap wie folgt::

    int *i = new int; 
    

    Der Unterschied besteht darin, dass das Stapelsegment Variable nach dem Verlassen der Funktion verloren

    Variablen können in dem Stapel-Segment mit diesem erzeugt werden aufrufen, während Speicher-Heap-Variablen bleiben, bis Sie sagen delete i;. Sie können ein Assemblersprachbuch lesen, um den Unterschied besser zu verstehen.

    Drittens:. Die Zeit, die Variable initialisiert ist

    Ein Stapel-Segment-Variable „Null initialisiert“ oder statisch-initialisiert“, wenn man den Funktionsaufruf treten sie in definiert sind

    A Gedächtnis- Die Heapvariable ist "nullinitialisiert" oder "statisch initialisiert", wenn sie zum ersten Mal vom Operator new erstellt wird.

    Schlussbemerkung

    können Sie darüber nachdenken, static int i; als globale Variable mit einem Umfang auf die Funktion beschränkt es in definiert ist. Ich denke, die Verwirrung über static int i; kommt, weil statisch noch etwas anderes bedeuten hören (es nicht zerstört wird, wenn Sie verlassen die Routine, so behält sie ihren Wert). Ich bin mir nicht sicher, aber ich denke, der Trick für static int i; ist es in den Stapel von main() zu setzen, was bedeutet, dass es nicht zerstört wird, bis Sie das gesamte Programm beenden (so behält es die erste Initialisierung), oder es könnte sein, dass es ist im Datensegment der Anwendung gespeichert.

    +4

    Diese Antwort enthält eine Menge Fehlinformationen. –

    +0

    Vergleicht man meine Antwort mit der von Matthieu M., kann ich nicht viel Unterschied sehen! Seltsam! – d777

    +0

    Nun, mindestens drei Leute stimmen nicht zu. Konkret - Ihre Definition von 'static initialization' ist falsch, Ihre Beschreibung von 'static int i' als" stack-based Variable "ist falsch und die Anweisung, die Sie über Assembly-Sprache lesen müssen, um mehr über die dynamische Zuweisung zu erfahren, ist falsch. Außerdem ist das Codebeispiel für "neu" falsch. Es gibt noch mehr, aber es lohnt sich kaum, es auseinander zu nehmen, wenn es schon eine andere vollkommen richtige Antwort gibt. –

    Verwandte Themen