2010-07-17 4 views
8

Я новичок на C++ и сталкиваюсь с проблемой.Когда память выделена статическим переменным в C++

Я прочитал в книге, что память выделяется статической переменной, как только объект создается из этого класса. Теперь, если я сделаю эту статическую переменную глобальной? Когда он будет инициализирован в этом случае?

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

Большое спасибо!

ответ

25

Во-первых: ОСТАНОВИТЕ ДУМАНИЕ О ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ В С И С ++, или вы увековете свое состояние замешательства. Проблема сложнее, чем в, например, 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, которые будут распределены по каждой записи функции и освобождены от каждой функции выход, таким образом, и его ценность уничтожена). Обратите внимание, что использование статических переменных внутри функций очень несовместимо с многопоточным и повторным подключением, но вы знаете очень хорошо, что вы делаете.

+2

Примечание: оно не является полностью неопределенным. Все переменные области видимости файла в одной и той же компиляционной единице инициализируются в порядке объявления/определения. Просто не указано, какой порядок находится в единицах компиляции (или даже если переменные области видимости файла в разных единицах компиляции переплетены во время инициализации). –

+0

В вышеприведенной программе: «global1» инициализируется сначала с 0. «global2» инициализируется вторым с 0. «x» инициализируется при первом вызове функции f(). –

+0

Я хотел бы добавить еще одно сомнение здесь. В чем разница между инициализацией статической функции и обычной функцией? Я прочитал, что даже обычные функции имеют только 1 копию, независимо от количества объектов - это очень похоже на статические функции ... – Ishi

8

Статические переменные вообще не хранятся в куче.

Неинициализированные статические переменные хранятся в сегменте BSS.

Инициализированная статическая переменная хранится в сегменте данных.

Вы можете прочитать эту статью, которая объясняет все это в большой путь: http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory

+0

Сохранен ли стандарт, специфичный для глобальных переменных? Если это так, я бы хотел получить ссылку со стандарта. –

1

На programstart (до основной) памяти будет выделено для статической глобальной переменной.

У меня нет идеи по второму вопросу.

Смежные вопросы