Каково время жизни статической переменной в функции C++?

359
задан Cœur 20 October 2018 в 22:05
поделиться

3 ответа

Время жизни функции 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
Созданный в нечто
Уничтоженный в нечто

C:>sample.exe 1
Созданный, в если
Созданный в нечто
Уничтоженный в нечто
Уничтоженный, в если

C:>sample.exe 1 2
Созданный в нечто
Созданный, в если
Уничтоженный в том, если
Уничтоженный в нечто

[0] С тех пор C++ 98 <глоток> [2] не имеет никакой ссылки на несколько потоков, как это будет, ведет себя в многопоточной среде, является неуказанным, и может быть проблематичным как упоминания Roddy.

[1] C++ 98 раздел 3.6.3.1 [basic.start.term]

[2] В C++ 11 помех инициализируются ориентированным на многопотоковое исполнение способом, это также известно как Волшебная Статика .

242
ответ дан Will Vousden 23 November 2019 в 00:19
поделиться

Motti прав относительно порядка, но существуют некоторые другие вещи рассмотреть:

Компиляторы обычно используют скрытую переменную флага, чтобы указать, были ли локальные помехи уже инициализированы, и этот флаг проверяется на каждой записи в функцию. Очевидно, это - маленький хит производительности, но что является большим количеством беспокойства, то, что этот флаг, как гарантируют, не будет ориентирован на многопотоковое исполнение.

, Если у Вас есть локальные помехи как выше, и foo, назван от нескольких потоков, у Вас могут быть условия состязания, вызывающие plonk, чтобы быть инициализированными неправильно или даже многократно. Кроме того, в этом случае plonk может быть разрушен различным потоком, чем тот, который создал его.

Несмотря на то, что говорит стандарт, я очень опасался бы фактического порядка локального статического разрушения, потому что возможно, что можно невольно полагаться на статическое существо, все еще допустимое после того, как это было разрушено, и это действительно трудно разыскать.

123
ответ дан Roddy 23 November 2019 в 00:19
поделиться

FWIW, Разработчик C++ Codegear не разрушает в ожидаемом порядке согласно стандарту.

C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if

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

8
ответ дан Roddy 23 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

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