Во-первых: ОСТАНОВИТЕ ДУМАНИЕ О ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ В С И С ++, или вы увековете свое состояние замешательства. Проблема сложнее, чем в, например, Python или Pascal, и поэтому вы не можете просто использовать одно слово для концепции (ов).
Во-вторых, нет «кучи» или «стека» - это данные операционной системы и процессора и не имеют ничего общего с абстрактной спецификацией языка C++.
Теперь переменные имеют 1) область действия, 2) связь и 3) класс хранения. Статическое ключевое слово используется для воздействия на все три аспекта, в зависимости от того, где вы его используете.
Область действия: где объявлена переменная. Если внутри функции это функция-scope, если она не является функцией, она является файловой областью (что вы, вероятно, называете «глобальной переменной»).
Ссылка: доступна ли переменная из других единиц компиляции (если ваша программа состоит из нескольких исходных файлов).
Класс хранения:
Статические переменные выделяются в реализации определенным образом при запуске программы, и они живут, пока программа не закончится. Они не могут быть «освобождены» или «перераспределены». (типичная реализация - сегменты BSS и DATA, о которых упоминали другие).
Автоматические переменные существуют только в области видимости функции, они выделяются (и, возможно, инициализируются) на запись функции (обычно в стеке процессора) и освобождаются от выхода функции.
Динамический класс - это то, что вы, вероятно, называете «кучей».Это переменные, хранилище которых напрямую управляется через malloc/free или new/delete. Хранение для статических переменных управляется ОЧЕНЬ другим способом, чем динамическое хранилище, и два типа хранилищ принципиально несовместимы.
Пример:
===
// ALL file-scope variables have static storage class
int global1; // file-scope, external linkage
static int global2; // file-scope, internal linkage
void f()
{
static int x; // static storage class, function-scope
int y; // automatic storage class, function-scope
free(&x); // ILLEGAL, WILL CRASH!
free(&y); // DITTO!
free(&global1); // DITTO!
}
===
Теперь все переменные со статическим классом хранения (global1, global2 и х) выделены и инициализируется перед запуском программы. Если вы не укажете начальные значения, они инициализируются по умолчанию в UNSPECIFIED ORDER. (Для примитивных типов это просто означает заполнение нулями).
Статические переменные освобождаются только при выходе из программы. Это означает, что «x» в функции f будет инициализироваться ТОЛЬКО ОДИН (при запуске программы) и что он будет СОЗДАТЬ ЕГО ЗНАЧЕНИЕ между вызовами функции (в отличие от y, которые будут распределены по каждой записи функции и освобождены от каждой функции выход, таким образом, и его ценность уничтожена). Обратите внимание, что использование статических переменных внутри функций очень несовместимо с многопоточным и повторным подключением, но вы знаете очень хорошо, что вы делаете.
Примечание: оно не является полностью неопределенным. Все переменные области видимости файла в одной и той же компиляционной единице инициализируются в порядке объявления/определения. Просто не указано, какой порядок находится в единицах компиляции (или даже если переменные области видимости файла в разных единицах компиляции переплетены во время инициализации). –
В вышеприведенной программе: «global1» инициализируется сначала с 0. «global2» инициализируется вторым с 0. «x» инициализируется при первом вызове функции f(). –
Я хотел бы добавить еще одно сомнение здесь. В чем разница между инициализацией статической функции и обычной функцией? Я прочитал, что даже обычные функции имеют только 1 копию, независимо от количества объектов - это очень похоже на статические функции ... – Ishi