Каково время жизни статических переменных класса в C++?
-
21-08-2019 - |
Вопрос
Если у меня есть класс под названием Test::
class Test
{
static std::vector<int> staticVector;
};
когда это статический вектор построить и когда он будет разрушен?
Это связано с созданием первого объекта класса Test или просто с обычными статическими переменными?
Просто чтобы уточнить: этот вопрос пришел мне в голову после прочтения «Концепции языков программирования» (Sebesta Ch-5.4.3.1), и там говорится::
Обратите внимание, что когда статический Модификатор появляется в объявлении переменной в определении класса в C ++, Java и C#, это не имеет ничего общего с временем жизни переменной.В этом контексте это означает, что переменная является переменной класса, а не переменной экземпляра.Многократное использование зарезервированного слова может быть запутанным, особенно с теми, кто изучает язык.
ты понимаешь?:(
Решение
Точно так же, как обычные статические (глобальные) переменные.
Другие советы
Я также хочу написать текст об инициализации, на который позже смогу дать ссылку.
Сначала список возможностей.
- Пространство имен Статический
- Сорт Статический
- Местный Статический
Статическое пространство имен
- Существует два метода инициализации. статический (предполагается, что это произойдет во время компиляции) и динамичный (предполагается, что это произойдет во время выполнения) инициализация.
- Статический Инициализация происходит раньше любая динамическая инициализация, независимо от отношений единиц трансляции.
- Динамический Инициализация упорядочена в единице трансляции, тогда как при статической инициализации нет определенного порядка.Объекты области пространства имен одной и той же единицы перевода динамически инициализируются в том порядке, в котором появляется их определение.
- Объекты типа POD, инициализируемые константными выражениями, инициализируются статически.На их значение можно положиться при динамической инициализации любого объекта, независимо от отношений единиц перевода.
- Если инициализация выдает исключение,
std::terminate
называется.
Примеры:
Следующая программа печатает 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;
- Динамический инициализация объекта не обязательно должна происходить до main любой ценой.Однако инициализация должна произойти до первого использования объекта или функции его единицы перевода.Это важно для динамически загружаемых библиотек.
Класс Статический
- Ведите себя как статика пространства имен.
- Существует отчет об ошибке о том, разрешено ли компилятору инициализировать статику класса при первом использовании функции или объекта ее единицы перевода (после main).Формулировка в стандарте в настоящее время допускает это только для объектов области пространства имен, но, похоже, она намерена разрешить это и для объектов области действия класса.Читать Объекты области пространства имен.
- Для статических классов, которые являются членами шаблонов, правило состоит в том, что они инициализируются только в том случае, если они когда-либо используются.Их неиспользование не приведет к инициализации.Обратите внимание, что в любом случае инициализация произойдет, как описано выше.Инициализация не будет отложена, поскольку он является членом шаблона.
Локальная статика
- Для локальной статики действуют особые правила.
- Объекты типа POD, инициализированные константным выражением, инициализируются до входа в их блок, в котором они определены.
- Другие локальные статические объекты инициализируются при первом прохождении управления через их определение.Инициализация не считается завершенной, когда генерируется исключение.В следующий раз инициализация будет повторена.
Пример:Следующая программа печатает 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++, в том числе при уничтожении временных объектов.
Он создается одновременно с созданием и уничтожением глобальных переменных вместе с глобальными переменными.
Проще говоря:
Статическая переменная-член создается при создании глобальных переменных.Порядок построения глобальных переменных не определен, но это происходит до входа в основную функцию.
Уничтожение происходит при уничтожении глобальных переменных.
Глобальные переменные уничтожаются в обратном порядке их создания;после выхода из основной функции.
С уважением,
Ованес
P.S.:Я предлагаю взглянуть на C++-Standard, который объясняет (определяет), как и когда создаются или уничтожаются глобальные или статические переменные-члены.
П.П.С.:Ваш код только объявляет статическую переменную-член, но не инициализирует ее.Для его инициализации необходимо написать в одном из модулей компиляции:
std::vector Test::staticVector;
или
std::vector Test::staticVector=std::vector(/* здесь параметры ctor */);
Некоторая конкретная информация о VC++, если вы ее используете:
- Создание статических переменных класса происходит одновременно с созданием других статических/глобальных переменных.
- В windows за эту конструкцию отвечает функция запуска CRT.Это фактическая точка входа большинства программ, которые вы компилируете (это функция, которая вызывает вашу функцию Main/Winmain).Кроме того, он отвечает за инициализацию всей поддержки среды выполнения C (например, она нужна вам для использования malloc).
- Порядок построения не определен, однако при использовании компилятора Microsoft VC порядок построения для базовых типов будет в порядке, например, запись разрешена и безопасна.
статика.ч:...Декларация MyClass...статическая константа int a;статический int b;статический int ar[];} statics.cpp:
const int MyClass::a = 2;
int MyClass::b = a+3;
int MyClass::ar[a] = {1,2}
Статическая переменная-член класса означает, что даже если существует несколько объектов одного и того же класса, переменная будет одинаковой для всех объектов класса.
Итак, я бы сказал, он создается, когда создается экземпляр первого объекта, и уничтожается, когда уничтожается последний объект.