Jaki jest czas życia zmiennych statycznych klasy w C++?

Jeśli mam klasę o nazwie Test::

class Test
{
    static std::vector<int> staticVector;
};

Kiedy staticVector zostanie skonstruowany, a kiedy zostanie zniszczony ?

Czy jest to instancja pierwszego obiektu klasy testowej, czy tak jak zwykłe zmienne statyczne ?

tak dla jasności, to pytanie przyszło mi do głowy po przeczytaniu koncepcji języków programowania (Sebesta Ch-5.4.3.1) i mówi ::

Zauważ, że gdy modyfikator statyczny pojawia się w deklaracja zmienna w definicji klasy w C++, Java i C#, nie ma to nic wspólnego z żywotność zmiennej. W tym kontekst, to znaczy, że zmienna jest zmienna klasy, a nie zmienna instancji. Wielokrotne użycie słowo zarezerwowane może być mylące szczególnie dla osób uczących się język.

Zrozumiałeś? :(

Author: AraK, 2009-07-03

6 answers

Dokładnie jak zwykłe statyczne (globalne) zmienne.

 12
Author: Magnus Hoff,
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-07-03 14:33:44

Chcę też napisać jakiś tekst o initializatonie, do którego później mogę się połączyć.


Najpierw lista możliwości.

  • Przestrzeń Nazw Static
  • Class Static
  • Local Static

Przestrzeń Nazw Statyczna

  • istnieją dwie metody inicjalizacji. inicjalizacja statyczna (zamierzona w czasie kompilacji) i inicjalizacja dynamiczna (zamierzona w czasie wykonywania).
  • statyczna Inicjalizacjadzieje się przed dowolną dynamiczną inicjalizacją, pomijając relacje jednostek translacyjnych.
  • dynamiczne Inicjalizacja jest uporządkowana w jednostce translacyjnej, podczas gdy nie ma określonego porządku w inicjalizacji statycznej. Obiekty przestrzeni nazw tej samej jednostki tłumaczenia są dynamicznie inicjowane w kolejności, w jakiej pojawia się ich definicja.
  • POD typuje obiekty inicjalizowane wyrażeniami stałymi są statycznie inicjowane. Ich wartość może być zależna od dynamicznej inicjalizacji dowolnego obiektu, bez względu na relacje jednostek translacji.
  • jeśli inicjalizacja rzuca wyjątek, wywoływana jest std::terminate.

Przykłady:

Następujący program drukuje A(1) A(2)

struct A { 
  A(int n) { std::printf(" A(%d) ", n); } 
};

A a(1);
A b(2);

I następujące, oparte na tej samej klasie, drukuje A(2) A(1)

extern A a;
A b(2);
A a(1);

Załóżmy, że istnieje jednostka translacji, w której msg jest zdefiniowana jako po

char const *msg = "abc";

Następnie następujące wydruki abc. Zauważ, że p otrzymuje dynamiczną inicjalizację. Ale ponieważ statyczna inicjalizacja (char const* jest typem POD, a "abc" jest stałym wyrażeniem adresu) z msg dzieje się wcześniej, jest to w porządku i msg jest gwarantowane, że zostanie poprawnie zainicjowana.

extern const char *msg;
struct P { P() { std::printf("%s", msg); } };
P p;
  • dynamiczne inicjalizacja obiektu nie jest wymagana przed main za wszelką cenę. Inicjalizacja musi nastąpić przed pierwsze użycie obiektu lub funkcji jego jednostki translacyjnej. Jest to ważne w przypadku bibliotek dynamicznych.

Class Static

  • zachowuj się jak statyka przestrzeni nazw.
  • jest raport o błędzie, czy kompilator może zainicjować statykę klasy również przy pierwszym użyciu funkcji lub obiektu swojej jednostki tłumaczenia (po main). Sformułowanie w standardzie obecnie dopuszcza to tylko dla obiektów zakresu przestrzeni nazw - ale wydaje się, że zamierza Zezwalaj na to także obiektom klasy scope. Odczyt obiektów zakresu przestrzeni nazw .
  • dla statyki klas, które są członkami szablonów, reguła jest taka, że są inicjalizowane tylko wtedy, gdy są kiedykolwiek używane. Nieużywanie ich nie ulegnie inicjalizacji. Zauważ, że w każdym przypadku inicjalizacja nastąpi tak, jak wyjaśniono powyżej. Inicjalizacja nie będzie opóźniona, ponieważ jest członkiem szablonu.

Local Static

  • dla statyki lokalnej, specjalne zasady zdarza się.
  • obiekty typu POD zainicjalizowane wyrażeniem stałym są inicjalizowane przed wprowadzeniem ich bloku, w którym są zdefiniowane.
  • inne lokalne obiekty statyczne są inicjalizowane przy pierwszym przejściu kontroli przez ich definicję. Inicjalizacja nie jest uważana za zakończoną, gdy wrzucany jest wyjątek. Inicjalizacja zostanie wypróbowana ponownie następnym razem.

Przykład: następujący program wypisuje 0 1:

struct C { 
  C(int n) { 
    if(n == 0)
      throw n;
    this->n = n;
  }
  int n;
};

int f(int n) {
  static C c(n);
  return c.n;
}

int main() {
  try { 
    f(0); 
  } catch(int n) { 
    std::cout << n << " "; 
  }
  f(1); // initializes successfully
  std::cout << f(2);  
}

We wszystkich powyższych przypadkach, w pewnych ograniczonych przypadkach, dla niektórych obiektów, które nie muszą być inicjowane statycznie, kompilator może inicjować statycznie, zamiast dynamicznie. Jest to trudny problem, zobacz ta odpowiedź aby uzyskać bardziej szczegółowy przykład.

Zauważ również, że kolejność zniszczenia jest dokładną kolejnością zakończenia budowy obiektów. Jest to powszechne i dzieje się we wszelkiego rodzaju sytuacje w C++, w tym w destrukcji.

 15
Author: Johannes Schaub - litb,
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
2017-05-23 11:54:22

Jest konstruowana w tym samym czasie, gdy zmienne globalne są konstruowane i niszczone wraz z globalami.

 4
Author: Goz,
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-07-03 14:34:46

Po prostu:
Statyczna zmienna składowa jest konstruowana, gdy zmienne globalne są konstruowane. Kolejność konstrukcji zmiennych globalnych nie jest zdefiniowana, ale dzieje się to przed wprowadzeniem funkcji main.

Zniszczenie następuje, gdy zmienne globalne są niszczone.

Zmienne globalne są niszczone w odwrotnej kolejności, w jakiej zostały skonstruowane; po wyjściu z funkcji main.

Pozdrawiam,
Ovanes

P. S.: proponuję rzucić okiem na C++-Standard, który wyjaśnia (definiuje) jak i kiedy globalne lub statyczne zmienne członkowskie są konstruowane lub niszczone.

P. P. S.: Twój kod deklaruje tylko statyczną zmienną członkowską, ale jej nie inicjalizuje. Aby go zainicjować musisz napisać w jednej z jednostek kompilacji:

Std:: vector Test:: staticVector;
lub
std:: vector Test:: staticVector=std:: vector (/*ctor params here*/);

 2
Author: ovanes,
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-07-03 16:16:44

Niektóre konkretne informacje VC++ w przypadku, gdy tego używasz:

  1. statyczna konstrukcja zmiennych klasy zachodzi w tym samym czasie co inne statyczne / globalne zmienne.
  2. w systemie windows za tę konstrukcję odpowiada funkcja uruchamiania CRT. Jest to rzeczywisty punkt wejścia większości programów, które kompilujesz (jest to funkcja, która wywołuje funkcję Main/Winmain). Ponadto jest on odpowiedzialny za inicjalizację całej obsługi środowiska uruchomieniowego C (na przykład potrzebujesz go do użycia malloc).
  3. kolejność budowy jest niezdefiniowana, jednak przy użyciu kompilatora Microsoft VC kolejność budowy dla typów podstawowych będzie OK, na przykład zapisanie

Statyka.h: ... Deklaracja MyClass ... static const int a; static int b; static int ar[]; } statyka.cpp:

const int MyClass::a = 2;
int MyClass::b = a+3;
int MyClass::ar[a] = {1,2}
 1
Author: Danra,
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-07-03 15:49:19

Statyczna zmienna klasy oznacza, że nawet jeśli istnieje wiele obiektów tej samej klasy, zmienna będzie taka sama dla wszystkich obiektów tej klasy.

Tak więc, powiedziałbym, jest on konstruowany, gdy pierwszy obiekt jest instancjowany i niszczony, gdy ostatni obiekt jest destructed.

 -1
Author: sulavshr,
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
2018-04-04 14:21:19