Kiedy inicjowane są statyczne Członkowie klasy C++?

Wydaje się, że nie ma łatwej odpowiedzi na to pytanie, ale czy są jakieś założenia, które można bezpiecznie sformułować, kiedy statyczne pole klasy może być dostępne?

EDIT: jedynym bezpiecznym założeniem wydaje się być to, że wszystkie statyki są inicjowane przed uruchomieniem programu (wywołanie do main). Tak więc, dopóki nie odwołuję się do statyki z innego statycznego kodu inicjującego, nie powinienem mieć się o co martwić?

Author: Tony the Pony, 2009-09-14

7 answers

Standard gwarantuje dwie rzeczy - że obiekty zdefiniowane w tej samej jednostce tłumaczeniowej (zwykle oznacza .plik cpp) są inicjalizowane w kolejności ich definicji ( nie deklaracje):

3.6.2

Przechowywanie obiektów o statycznym czasie przechowywania (basic.stc.statyczna) jest zerowa (dcl.init) przed jakąkolwiek inną inicjalizacją. Zero-inicjalizacja i inicjalizacja z wyrażeniem stałym są zbiorczo nazywane statycznymi inicjalizacja; wszystkie inne inicjalizacje są inicjalizacją dynamiczną. Obiekty typu POD (basic.typy) ze statycznym czasem przechowywania zainicjalizowanym wyrażeniami stałymi (expr.const) należy zainicjować przed jakąkolwiek dynamiczną inicjalizacją. Obiekty o statycznym czasie przechowywania zdefiniowanym w przestrzeni nazw w tej samej jednostce tłumaczenia i dynamicznie inicjalizowanym są inicjalizowane w kolejności, w jakiej ich definicja pojawia się w jednostce tłumaczenia.

The other gwarantowane jest to, że inicjalizacja obiektów statycznych z jednostki tłumaczeniowej zostanie wykonana przed użyciem dowolnego obiektu lub funkcji z tej jednostki tłumaczeniowej:

Jest definiowane przez implementację, czy dynamiczna inicjalizacja (dcl.init, Klasa.statyczne, Klasa.ctor, Klasa.expl.INIT) obiektu przestrzeni nazw scope jest wykonywane przed pierwszą instrukcją main. Jeśli inicjalizacja zostanie odroczona do pewnego punktu w czasie po pierwszej instrukcji main, nastąpi to przed pierwsze użycie dowolnej funkcji lub obiektu zdefiniowanego w tej samej jednostce tłumaczeniowej co inicjowany obiekt.

Nic innego nie gwarantowałem (szczególnie kolejność inicjalizacji obiektów zdefiniowanych w różnych jednostkach translacyjnych jest zdefiniowana implementacja).

edytuj Jak zaznaczono w komentarzu Sumy, gwarantuje się również, że zostaną one zainicjowane przed wpisaniem main.

 50
Author: Tadeusz Kopec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-07 09:17:28

Są inicjowane przed uruchomieniem programu (tj. przed wprowadzeniem main).

Gdy w pojedynczym pliku CPP znajdują się dwie lub więcej definicji (danych statycznych), są one inicjalizowane w kolejności, w jakiej są zdefiniowane w pliku (Ta zdefiniowana wcześniej/wyższa w pliku jest inicjowana przed następną).

Jeśli istnieją dwie lub więcej definicji (danych statycznych) w więcej niż jednym pliku CPP, Sekwencja, w której przetwarzane są pliki CPP jest undefined/implementation-specific. Problem polega na tym, że konstruktor zmiennej globalnej (wywołanej przed uruchomieniem programu) odwołuje się do innej zmiennej globalnej zdefiniowanej w innym pliku CPP, która mogła jeszcze nie zostać skonstruowana. Jednak pozycja 47 efektywnego C++ (który nosi tytuł zapewnia, że obiekty globalne są inicjalizowane przed ich użyciem ) opisuje obejście ...

  • Definiowanie zmiennej statycznej w pliku nagłówkowym (jest to statyczna możesz więc mieć wiele jego instancji bez narzekania linkera)

  • Niech konstruktor tej zmiennej wywoła wszystko, czego potrzebujesz (w szczególności, zbuduj globalne singletony zadeklarowane w nagłówkach)

... jest to technika, która może być użyta w niektórych plikach nagłówkowych systemu, np. w celu zapewnienia, że zmienna globalna cin jest zainicjalizowana, zanim nawet konstruktory zmiennych statycznych jej użyją.

 17
Author: ChrisW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-14 14:21:35

Twój ostateczny wniosek w edycji jest poprawny. Ale problem polega na tym, że klasa sama w sobie jest statyczna. Łatwiej jest powiedzieć, że mój kod będzie miał członków klasy static, które nie odnoszą się do innych globalnych danych/ członków klasy static, ale gdy wybierzesz tę trasę, wkrótce wszystko pójdzie nie tak. Jedno podejście, które uznałem za przydatne w praktyce, aby nie mieć klasy static data members, ale klasy static wrapper methods. Metody te mogą następnie trzymać statyczny obiekt w sobie. Na np.

TypeX* Class2::getClass1Instance()
{
    static TypeX obj1;
    return &obj1;
}

Uwaga: wcześniejsza odpowiedź mówi:

Inną gwarantowaną rzeczą jest to, że inicjalizacja obiektów statycznych z jednostki tłumaczeniowej zostanie wykonana przed użyciem jakiegokolwiek obiektu lub function from this translation unit

Nie jest to całkowicie poprawne i norma jest błędnie wnioskowana tutaj. Może to nie być prawdziwe, jeśli funkcja z jednostki tłumaczeniowej zostanie wywołana przed wprowadzeniem main.

 3
Author: Paani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-22 09:57:31

Wierzę, że można uzyskać do niego dostęp w każdej chwili podczas egzekucji. To, co pozostaje nieokreślone, to kolejność inicjalizacji zmiennych statycznych.

 1
Author: erelender,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-14 13:57:29

Mogą być inicjowane w pliku implementacji (.C/cpp / CC) plików. Nie inicjuj ich .H jako kompilator będzie narzekał na wiele definicji.

Są zazwyczaj inicjowane przed main, jednak kolejność jest uknown, dlatego należy unikać zależności. Z pewnością mogą być dostępne w ramach funkcji członka. Należy pamiętać, że kolejność inicjalizacji nie jest znana dla statycznych członków. Proponuję zamknąć statyczny element w funkcji statycznej, która sprawdzi, czy element ma zainicjowany.

 1
Author: vehomzzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-14 13:58:17

Nie ma całkowicie trywialnej odpowiedzi na to pytanie, ale zasadniczo są one inicjowane tuż przed przekazaniem kontroli do punktu wejścia (głównego) programu. Kolejność ich inicjalizacji jest (według mojej wiedzy) niezdefiniowana i może być specyficzna dla kompilatora.

EDIT: aby wyjaśnić, twoje dodane założenie jest poprawne. Tak długo, jak masz do niego dostęp tylko po wpisie głównym, tak naprawdę nie musisz się martwić o to, kiedy/jak zostanie zainicjowany. Zostanie zainicjowany do tego czasu.

 0
Author: Dentoid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-14 14:14:03

Myślę, że główny wątek procesu wykona następujące pięć kroków w kolejności

  1. Inicjalizacja biblioteki CRT

  2. Inicjalizacja statyczna

  3. Wykonanie funkcji main ()

  4. Unitializacja statyczna

  5. Unitializacja biblioteki CRT

Chcesz statyki odniesienia z innego statycznego kodu inicjalizacyjnego? może działają następujące Kody:

class A;
static auto_ptr<A> a(auto_ptr<A>(&GetStaticA()));
A &GetStaticA(void)
{
    static A *a = NULL; //the static basic type variables initialized with constant experession will be initialized earlier than the other static ones
    if (a == NULL)
    {
         a = new A();
         return *a;
    }
}
 -1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-14 14:57:41