Распределение памяти статической переменной внутри функций - PullRequest
0 голосов
/ 02 января 2019
static void func1(){
    static int i(9);
};

Выделена ли память для статической переменной i при вызове функции или при запуске программы?

Ответы [ 2 ]

0 голосов
/ 02 января 2019

В данном конкретном случае все зависит от реализации. Во-первых, вопрос распределения.

Это правда, что стандарт гласит, что статические переменные продолжительности хранения инициализируются как следствие запуска программы. См. Например C++17 [basic.static.start]:

(1) Переменные со статической продолжительностью хранения инициализируются в результате запуска программы.

Это может указывать на то, что память должна быть выделена до того, как main даже запустится. Однако C ++ (как и C) также следует правилу «как если бы», которое гласит:

... реализация может свободно игнорировать любое требование настоящего Международного Стандарта при условии, что в результате будет выполнено требование, насколько это можно определить из наблюдаемого поведения программа.

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

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

Однако, поскольку вы используете константу 9 для инициализации целого числа (и это 9 не изменится ни в одной точке во время выполнения программы), это явно подпадает под части константы инициализатора стандарта. В этом случае переменную нужно просто купить и инициализировать перед использованием, так что это можно сделать в любой момент между инициацией программы и первоначальным объявлением.

Это покрыто текстом:

(3) Реализации разрешается выполнять инициализацию переменной со статической или продолжительностью хранения потока в качестве статической инициализации, даже если такая инициализация не требуется выполнять статически, при условии, что (3.1) динамическая версия инициализации не изменяет значение какого-либо другого объекта статической или длительности хранения потока до его инициализации; и (3.2) статическая версия инициализации создает в инициализированной переменной то же значение, что и динамическая инициализация, если бы все переменные, которые не требуется статически инициализировать, инициализировались динамически.


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

В этом конкретном случае не имеет значения, происходит ли выделение и / или инициализация до main или при первом обнаружении объявления. Вероятно, все изменится, как только вы начнете иметь нетривиальные конструкторы или деструкторы, но не в этом случае.

0 голосов
/ 02 января 2019

Память для переменной static выделяется при запуске программы, но переменная не инициализируется до тех пор, пока функция не будет вызвана в первый раз.

...