Как программа узнает, нужно ли инициализировать статическую переменную?
Как в заголовке - как программа узнает, что foo
уже инициализируется, когда функция вызывается во второй раз:
int getFoo()
{
static int foo = 30;
return foo;
}
int main()
{
getFoo();
getFoo();
}
Я хочу знать, хранит ли программа какую-то дополнительную информацию о том, какая статическая переменная уже была инициализирована.
Редактировать:
Я нашел ответ здесь:
Почему при инициализации локальных статических объектов используются скрытые защитные флаги?
Как я уже догадался - большинство компиляторов хранят дополнительную "переменную защиты".
2 ответа
Посмотрите на [stmt.dcl] / 4:
- Динамическая инициализация переменной области блока со статической продолжительностью хранения или продолжительностью хранения потока выполняется при первом прохождении контроля через ее объявление; такая переменная считается инициализированной после завершения ее инициализации. Если инициализация завершается выдачей исключения, инициализация не завершена, поэтому она будет повторена при следующем входе элемента управления в объявление. Если элемент управления вводит объявление одновременно во время инициализации переменной, параллельное выполнение должно ожидать завершения инициализации.94 Если элемент управления повторно вводит объявление рекурсивно, пока переменная инициализируется, поведение не определено.
Вы должны быть осторожны здесь. Примитивный static
s инициализируются во время компиляции, поэтому в вашем примере, GetFoo
просто, по сути, возвращает константу.
ТЕМ НЕ МЕНИЕ...
static
s, которые инициализируют объект (или инициализируют примитив, вызывая функцию), выполняют указанную инициализацию, когда область, в которой они объявлены, вводится впервые.
Кроме того, в C++ 11 это должно быть сделано потокобезопасным способом, который генерирует много дополнительного кода (хотя и не сильно загружается во время выполнения после первого раза), и это может быть проблемой, скажем, на микроконтроллере где размер кода часто имеет значение.
Вот конкретный пример:
#include <iostream>
struct X
{
X () { std::cout << "Initialising m\n"; m = 7; }
int m;
};
void init_x ()
{
static X x;
}
int main () {
std::cout << "main called\n";
init_x ();
std::cout << "init_x returned\n";
}
Выход:
main called
Initialising m
init_x returned
Демонстрационная версия: https://wandbox.org/permlink/NZApcYYGwK36vRD4
Сгенерированный код: https://godbolt.org/z/UUcL9s