Вопрос по c++ – Каково время жизни статических переменных класса в C ++?

9

Если у меня есть класс с именем Test ::

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

когдаstaticVector построить и когда он разрушается?

Это связано с созданием первого объекта класса Test или с обычными статическими переменными?

Just to clarify, this question came to my mind after reading Concepts of Programming Languages (Sebesta Ch-5.4.3.1) and it says ::

Note that when the static modifier appears in the declaration of a variable in a class definition in C++, Java and C#, it has nothing to do with the lifetime of the variable. In that context, it means the variable is a class variable, rather than an instance variable. The multiple use of a reserved word can be confusing particularly to those learning the language.

did you understand? :(

Ваш Ответ

6   ответов
12

Точно так же, как обычные статические (глобальные) переменные.

Порядок уничтожения статических / глобальных переменных является обратным порядком создания.
Я бы также добавил, что именно так создаются переменные в любых пространствах имен. Глобальные и неглобальные (std::cout это пример).
Единственное, что нужно сделать в дополнение к этому, это то, что порядок создания статической / глобальной переменной не определен.
@skizz: В определенном модуле компиляции порядок четко определен как порядок объявления. В нескольких единицах компиляции он не определен (или не указан). Но вопрос о разрушении.
Некоторые придирки, но важные придирки: порядок зависит от их порядка определения, а не от порядка объявления: в следующем коде a создается после b, даже если a объявлено до b:extern A a; B b(a); A a; - этот код может дать удивительные результаты.
4

Он создается одновременно с глобальными переменными, а также с глобальными переменными.

Да, но он не спрашивал о статических переменных функций ... но да ... вы правы.
При первом использовании статические переменные функции не создаются. Если они не используются, они никогда не создаются. Кроме того, поскольку они создаются при первом использовании, их порядок зависит от порядка вызова функций / методов.
1

Некоторая конкретная информация VC ++ в случае, если вы используете то, что вы используете:

  1. Static class variables construction occurs at same time as other static/global variables.
  2. In windows, the CRT startup function is responsible for this construction. This is the actual entry point of most programs you compile (it is the function which calls your Main/Winmain function). In addition, it is responsible for initializing the entire C runtime support (for example you need it to use malloc).
  3. The order of construction is undefined, however when using the microsoft VC compiler the order of construction for basic types will be OK, for example it is legal and safe to write

statics.h: ... MyClass declaration ... static const int a; static int b; static int ar[]; } statics.cpp:

const int MyClass::a = 2;
int MyClass::b = a+3;
int MyClass::ar[a] = {1,2}
Вопрос касается C ++, а не Visual C ++ или Windows. Последние версии MSVC соответствуют стандарту, но вы не можете использовать один компилятор в качестве ссылки или доказательства. Стандарт должен быть определенным источником, на который вы должны полагаться. Время жизни глобальных или статических переменных-членов и их инициализация очень хорошо описаны в стандарте. Почему вы используете статический спецификатор для переменных, не являющихся членами? Это заставит их иметь внутреннюю связь! Я думаю, что у вас будут ошибки связывания в других модулях компиляции как statics.cpp.
15

Я тоже хочу написать текст об инициализации, на который позже смогу сослаться.


Сначала список возможностей.

  • Namespace Static
  • Class Static
  • Local Static

Namespace Static

  • There are two initialization methods. static (intended to happen at compile time) and dynamic (intended to happen at runtime) initialization.
  • Static Initialization happens before any dynamic initialization, disregarding of translation unit relations.
  • Dynamic Initiaization is ordered in a translation unit, while there is no particular order in static initialization. Objects of namespace scope of the same translation unit are dynamically initialized in the order in which their definition appears.
  • POD type objects that are initialized with constant expressions are statically initialized. Their value can be relied on by any object's dynamic initialization, disregarding of translation unit relations.
  • If the initialization throws an exception, std::terminate is called.

Примеры:

Следующая программа печатаетA(1) A(2)

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

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

И следующее, основанное на том же классе, печатаетA(2) A(1)

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

Давайте представим, что есть блок перевода, гдеmsg определяется как следующее

char const *msg = "abc";

Тогда следующие отпечаткиabc, Обратите внимание, чтоp получает динамическую инициализацию. А потому что статическая инициализация (char const* это тип POD, и"abc" является адресным константным выражением)msg случается до этого, это нормально, иmsg гарантированно будет правильно инициализирован.

extern const char *msg;
struct P { P() { std::printf("%s", msg); } };
P p;
  • Dynamic initialization of an object is not required to happen before main at all costs. The initialization must happen before the first use of an object or function of its translation unit, though. This is important for dynamic loadable libraries.

Class Static

  • Behave like namespace statics.
  • There is a bug-report on whether the compiler is allowed to initialize class statics on the first use of a function or object of its translation unit too (after main). The wording in the Standard currently only allows this for namespace scope objects - but it seems it intends to allow this for class scope objects too. Read Objects of Namespace Scope.
  • For class statics that are member of templates the rule is that they are only initialized if they are ever used. Not using them will not yield to an initialization. Note that in any case, initialization will happen like explained above. Initialization will not be delayed because it's a member of a template.

Local Static

  • For local statics, special rules happen.
  • POD type objects initialized with constant expression are initialized before their block in which they are defined is entered.
  • Other local static objects are initialized at the first time control passes through their definition. Initialization is not considered to be complete when an exception is thrown. The initialization will be tried again the next time.

Пример: распечатывается следующая программа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);  
}

Во всех вышеупомянутых случаях, в определенных ограниченных случаях, для некоторых объектов, которые не должны быть статически инициализированы, компилятор может статически инициализировать его, вместо динамической инициализации. Это сложная проблема, см.этот ответ для более подробного примера.

Также отметим, что порядок уничтожения является точным порядком завершения строительства объектов. Это обычное явление, которое встречается во всех ситуациях в C ++, в том числе при разрушении временных.

Отличное объяснение. AraK
@AraK, спасибо :)
-1

Статическая переменная-член класса означает, что, хотя существует несколько объектов одного класса, эта переменная будет одинаковой для всех объектов класса.

Так что, я бы сказал, он создается, когда первый объект создается и разрушается, когда последний объект удаляется.

Так ты не уверен? Пожалуйста, отвечайте, только если вы уверены, что то, что вы говорите, верно :). В противном случае ответ не имеет значения для других пользователей.
2

Проще говоря:
Статическая переменная-член создается при создании глобальных переменных. Порядок построения глобальных переменных не определен, но это происходит до ввода основной функции.

Разрушение происходит, когда глобальные переменные уничтожаются.

Глобальные переменные уничтожаются в обратном порядке их построения; после выхода из основной функции.

С Уважением,
Ованес

П.С .: Я предлагаю взглянуть на C ++ - Standard, который объясняет (определяет) ho, w и когда глобальные или статические переменные-члены создаются или разрушаются.

P.P.S .: Ваш код только объявляет статическую переменную-член, но не инициализирует ее. Для его инициализации вы должны написать в одном из модулей компиляции:

std :: vector Test :: staticVector;
или же
std :: vector Test :: staticVector = std :: vector (/ * параметры ctor здесь * /);

Похожие вопросы