Żywotność static
zmiennych funkcyjnych rozpoczyna się po raz pierwszy [0], gdy przepływ programu napotyka deklarację i kończy się wraz z zakończeniem programu. Oznacza to, że środowisko wykonawcze musi wykonać księgowość, aby zniszczyć ją tylko wtedy, gdy została faktycznie zbudowana.
Dodatkowo, ponieważ norma mówi, że niszczyciele obiektów statycznych muszą działać w odwrotnej kolejności do zakończenia ich budowy [1] , a kolejność budowy może zależeć od konkretnego uruchomienia programu, należy wziąć pod uwagę kolejność budowy .
Przykład
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Wynik:
C:> sample.exe
Utworzono w foo
Zniszczono w foo
C:> sample.exe 1
Utworzono w, jeśli
Utworzono w foo
Zniszczono w foo
Zniszczono w, jeśli
C:> sample.exe 1 2
Utworzono w foo
Utworzono w przypadku
zniszczenia w przypadku
zniszczenia w foo
[0]
Ponieważ C ++ 98 [2] nie ma odniesienia do wielu wątków, jak to będzie się zachowywać w środowisku wielowątkowym, jest nieokreślone i może być problematyczne, jak wspomina Roddy .
[1]
Sekcja C ++ 98 3.6.3.1
[basic.start.term]
[2]
W C ++ 11 statyka jest inicjowana w sposób bezpieczny dla wątków, jest to również znane jako Magic Statics .
[basic.start.term]
Motti ma rację co do zamówienia, ale jest kilka innych rzeczy do rozważenia:
Kompilatory zwykle używają ukrytej zmiennej flagi, aby wskazać, czy lokalna statystyka została już zainicjowana, a ta flaga jest sprawdzana przy każdym wejściu do funkcji. Oczywiście jest to niewielki hit wydajnościowy, ale bardziej niepokojące jest to, że ta flaga nie jest gwarantowana pod kątem bezpieczeństwa wątków.
Jeśli masz lokalny statyczny jak wyżej i
foo
jest wywoływany z wielu wątków, możesz mieć warunki wyścigu powodujące,plonk
że będzie on inicjowany niepoprawnie lub nawet wiele razy. Również w tym przypadkuplonk
może zostać zniszczony przez inny wątek niż ten, który go skonstruował.Pomimo tego, co mówi standard, byłbym bardzo ostrożny z faktyczną kolejnością lokalnego niszczenia statycznego, ponieważ możliwe jest, że możesz nieświadomie polegać na istnieniu ładunków statycznych po zniszczeniu, a to jest naprawdę trudne do wyśledzenia.
źródło
Istniejące wyjaśnienia nie są tak naprawdę kompletne bez rzeczywistej reguły ze Standardu, znalezionej w 6.7:
źródło
FWIW, Codegear C ++ Builder nie niszczy w oczekiwanej kolejności zgodnie ze standardem.
... co jest kolejnym powodem, aby nie polegać na nakazie zniszczenia!
źródło
Te zmienne statyczne są wchodzić w grę kiedyś rozpoczęciu wykonywania programu i pozostają dostępne aż po krańce wykonywania programu.
Zmienne statyczne są tworzone w segmencie danych pamięci .
źródło