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

StackOverflow https://stackoverflow.com/questions/1079623

  •  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++, если вы ее используете:

  1. Создание статических переменных класса происходит одновременно с созданием других статических/глобальных переменных.
  2. В windows за эту конструкцию отвечает функция запуска CRT.Это фактическая точка входа большинства программ, которые вы компилируете (это функция, которая вызывает вашу функцию Main/Winmain).Кроме того, он отвечает за инициализацию всей поддержки среды выполнения C (например, она нужна вам для использования malloc).
  3. Порядок построения не определен, однако при использовании компилятора 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}

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top