2017-08-09 95 views
9

Napotkane ostatnio zapytanie o porządek inicjalizacji statycznej C++ podczas przeglądu kodu.Czy inicjalizacja elementu statycznego klasy jest gwarantowana przed inicjalizacją statycznego obiektu tej klasy?

  1. mam klasę ze statycznej zmiennej składowej w jednostce kompilacji
  2. mam statyczny obiekt tej klasy przy użyciu konstruktora w innej jednostce kompilacji

Tutaj chcę wiedzieć, czy statyczna zmienna składowa ma być zainicjowana przed wywołaniem statycznego konstruktora obiektów?

MyClass.h:

typedef int (*MyFunc)(int); 
class MyClass { 
MyClass(MyFunc fptr) { 
    mFunc = fptr; 
} 
static MyFunc mFunc; 
} 

MyClass.cpp:

MyFunc MyClass::mFunc = nullptr; 

MyDifferentClass.h:

MyDifferentClass { 
public: 
    static int MyStaticFunc(int); 
} 

MyDifferentClass.cpp:

static MyClass myClassObj(MyDifferentClass::MyStaticFunc); 

W kodzie, by mFunc być inicjowane nullptr przed myClassObj zostanie stworzony? Powodem zapytania jest to, że jeśli zamówienie nie jest gwarantowane, wówczas mFunc może zostać ponownie zainicjowane na nullptr.

+0

Nie ma powodu, aby tolerować nieznane, ani pozostawić tego linkowi. Po prostu upewnij się, że sekwencja używa jawnego kodu na początku w main(). –

Odpowiedz

6

W kodzie, by mFunc być inicjowane nullptr przed myClassObj zostanie stworzony? Powodem zapytania jest to, że jeśli zamówienie nie jest gwarantowane, wówczas mFunc może zostać ponownie zainicjowane na nullptr.

Odpowiedź na pytanie brzmi "tak".

Pomijając kwestię inicjalizacji wątku określonych obiektów, inicjowanie zmiennych nielokalnych odbywa się w następującej kolejności.

  1. Wszystkie zmienne są inicjowane od zera (kolejność nie została określona). Nazywa się to zero inicjalizacji.
  2. Wszystkie zmienne, które można zainicjować za pomocą wartości stałych, są inicjowane. Nazywa się to stałą inicjalizacją .

Te (1 i 2 powyżej) nazywane są Inicjalizacja statyczna.

Po tym nastąpi inicjalizacja dynamiczna.

W twoim przypadku, MyClass::mFunc jest inicjowany za pomocą stałą podczas inicjalizacjimyClassObj jest inicjowany za pomocą dynamicznej inicjalizacji. W związku z tym pierwsza z nich jest gwarantowana jako pierwsza.

Więcej na ten temat można znaleźć pod adresem https://timsong-cpp.github.io/cppwp/n3337/basic.start.init.

+1

Cytujesz C++ 11, ale wiele [podstawa podstawy została zmieniona z powodu raportu o usterce 2026] (https://stackoverflow.com/a/34276374/1708801) z różnych powodów. Więc uważaj. –

+0

@ShafikYaghmour, Dzięki. To dobra informacja. –