/ / Verschobene Initialisierungsreihenfolge in C ++ 11 - C ++, C ++ 11, Sprachanwalt, static-order-fiasco

Verzögerte Initialisierungsreihenfolge in C ++ 11 - C ++, C ++ 11, Sprach-Anwalt, Statisches-Ordnungs-Fiasko

Betrachten Sie den folgenden Code, der auf drei Kompilierungseinheiten aufgeteilt ist:

a.h:

struct A
{
void Register(const char* s);

const char* m_s[10];
int m_i = 0;
};

A& GetA();

a.cpp:

#include "a.h"
#include <stdio.h>

void A::Register(const char* s)
{
m_s[m_i++] = s;
}

A& GetA()
{
static A instance;
return instance;
}

int main(int argc, char* argv[])
{
A& a = GetA();
int n = a.m_i;
for (int i = 0; i < n ; ++i)
printf("%sn", a.m_s[i]);
return 0;
}

b.cpp:

#include "a.h"
struct B
{
B() { GetA().Register("b"); }

static B* instance;
};
B* B::instance = new B;

c.cpp:

#include "a.h"
struct C
{
C() { GetA().Register("c"); }

static C* instance;
};
C* C::instance = new C;

Der Code wird mit gcc (-std = c ++ 11) erstellt und ausgeführt und erzeugt die Ausgabe:

c
b

Nun, bezogen auf cppreference.com:

Verzögerte dynamische Initialisierung

Es ist implementierungsdefiniert, ob dynamischInitialisierung passiert - vor der ersten Aussage der Hauptfunktion (für Statik) oder die anfängliche Funktion des Threads (für Thread-Locals) oder verzögert nach dem geschehen

Bei der Initialisierung einer Nicht-Inline-Variablenist verzögert nach der ersten Anweisung der Haupt- / Thread-Funktion, es geschieht vor der ersten odr-Verwendung einer Variablen mit static / thread Speicherdauer, die in derselben Übersetzungseinheit wie die Variable definiert ist initialisiert werden. Wenn keine Variable oder Funktion aus einem gegebenen Wert verwendet wird Übersetzungseinheit, die in dieser Übersetzung definierten nichtlokalen Variablen Die Einheit darf niemals initialisiert werden (dies modelliert das Verhalten einer dynamische On-Demand-Bibliothek). Allerdings solange nichts von einer TU ist odr-verwendet alle nicht lokalen Variablen, deren Initialisierung oder Zerstörung hat Nebenwirkungen werden auch dann initialisiert, wenn sie nicht im Internet verwendet werden Programm.

Beachten Sie, dass a.cpp ist sich der Existenz von nicht bewusst B und Cund dass die einzigen Wechselwirkungen von B & C mit A sind die Aufrufe von GetA() und A::Register() während der Konstruktion ihrer jeweiligen Instanzen.

Soweit ich sehen kann, die B & C Instanzen werden nicht von ODR verwendet und schon gar nicht von main()s Übersetzungseinheit. Ihre Initialisierung hat eindeutig Nebenwirkungen, aber es scheint mir, dass es keine Garantie dafür gibt, dass diese Initialisierung vor dem Einstieg erfolgt main(), oder davor main() druckt die registrierten Zeichenfolgen - oder überhaupt.

So endlich - Meine Frage ist das: Ist die Tatsache, dass die B und C Instanzen werden vorher initialisiert main() gibt die registrierten Zeichenfolgen aus nicht zum Standard, aber zu gccs implementierungsdefiniertem Verhalten?

Wenn der Standard dies garantiert, wie?

Antworten:

0 für die Antwort № 1

Ist die Tatsache, dass die B und C Instanzen werden vorher initialisiert main() druckt die registrierten Zeichenfolgen nicht nach dem Standard, sondern nach dem von gcc implementierten Verhalten

Es ist nicht garantiert durch standard. Der relevanteste Teil des Zitats:

Wenn keine Variable oder Funktion aus einer gegebenen Übersetzungseinheit verwendet wird, können die in dieser Übersetzungseinheit definierten nicht lokalen Variablen niemals initialisiert werden

Da keine Funktion oder Variable verwendet wurde b.cpp Noch c.cppIhre statischen Variablen sind möglicherweise (hinsichtlich der dynamischen Initialisierung) nicht initialisiert, und daher sind die Nebenwirkungen ihrer Initialisierung möglicherweise nicht sichtbar.


In der Praxis würde ich die gezeigten erwarten,Initialisierungsverhalten, wenn die Übersetzungseinheiten statisch verknüpft sind, und das mögliche Nichtinitialisierungsverhalten, wenn sie dynamisch geladen werden (gemeinsam genutzte Bibliothek). Der Standard garantiert jedoch keine, da er nicht das Verhalten von gemeinsam genutzten Bibliotheken angibt.