Вопрос по c++ – Каково время жизни статических переменных класса в C ++?
Если у меня есть класс с именем 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? :(
Некоторая конкретная информация VC ++ в случае, если вы используете то, что вы используете:
- Static class variables construction occurs at same time as other static/global variables.
- 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).
- 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}
Я тоже хочу написать текст об инициализации, на который позже смогу сослаться.
Сначала список возможностей.
- 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 ++, в том числе при разрушении временных.
Проще говоря:
Статическая переменная-член создается при создании глобальных переменных. Порядок построения глобальных переменных не определен, но это происходит до ввода основной функции.
Разрушение происходит, когда глобальные переменные уничтожаются.
Глобальные переменные уничтожаются в обратном порядке их построения; после выхода из основной функции.
С Уважением,
Ованес
П.С .: Я предлагаю взглянуть на C ++ - Standard, который объясняет (определяет) ho, w и когда глобальные или статические переменные-члены создаются или разрушаются.
P.P.S .: Ваш код только объявляет статическую переменную-член, но не инициализирует ее. Для его инициализации вы должны написать в одном из модулей компиляции:
std :: vector Test :: staticVector;
или же
std :: vector Test :: staticVector = std :: vector (/ * параметры ctor здесь * /);