Время жизни функциональных static
переменных начинается в первый раз, когда [0] поток программы встречает объявление, и заканчивается при завершении программы. Это означает, что среда выполнения должна вести какую-то бухгалтерию, чтобы разрушить ее только в том случае, если она действительно была построена.
Кроме того, поскольку в стандарте говорится, что деструкторы статических объектов должны запускаться в порядке, обратном завершению их построения [1] , и порядок построения может зависеть от конкретного запуска программы, необходимо учитывать порядок построения. ,
пример
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Вывод:
C:> sample.exe
Создано в foo
Уничтожено в foo
C:> sample.exe 1
Создан, если
Создан в foo
Разрушен в foo
Разрушен в if
C:> sample.exe 1 2
Создан в foo
Создан, если
уничтожен, если
уничтожен в foo
[0]
Поскольку C ++ 98 [2] не имеет ссылки на несколько потоков, то, как это будет вести себя в многопоточной среде, не определено, и это может быть проблематично, как упоминает Родди .
[1]
C ++ 98 раздел 3.6.3.1
[basic.start.term]
[2]
В C ++ 11 статика инициализируется потокобезопасным способом, это также называется Magic Statics .
[basic.start.term]
Мотти прав насчет порядка, но есть некоторые другие вещи, которые следует учитывать:
Компиляторы обычно используют переменную скрытого флага, чтобы указать, была ли локальная статика уже инициализирована, и этот флаг проверяется при каждой записи в функцию. Очевидно, это небольшой удар по производительности, но больше всего беспокоит то, что этот флаг не гарантированно является потокобезопасным.
Если у вас есть локальная статика, как указано выше, и она
foo
вызывается из нескольких потоков, могут возникнуть условия гонки, приводящиеplonk
к неправильной инициализации или даже к нескольким разам. Кроме того, в этом случаеplonk
может быть разрушен другой поток, чем тот, который его создал.Несмотря на то, что говорится в стандарте, я бы очень настороженно отнесся к фактическому порядку локального статического разрушения, потому что вполне возможно, что вы можете невольно полагаться на статичность, которая остается в силе после ее разрушения, и это действительно трудно отследить.
источник
Существующие объяснения на самом деле не полны без действительного правила из Стандарта, найденного в 6.7:
источник
FWIW, Codegear C ++ Builder не разрушает в ожидаемом порядке в соответствии со стандартом.
... что является еще одной причиной не полагаться на порядок уничтожения!
источник
В переменных Статическом пришел в игру , как только начинает выполнение программы и остается доступными до концов выполнения программы.
Статические переменные создаются в сегменте данных памяти .
источник