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

Этот сочетает в себе как оригинальный ответ Роба, так и обновление Pilau за 2016 год

    var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
var isIE = /*@cc_on!@*/false || !!document.documentMode;
// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;
// Chrome 1+
var output = 'Detecting browsers by ducktyping:
'; output += 'isFirefox: ' + isFirefox + '
'; output += 'isChrome: ' + isChrome + '
'; output += 'isSafari: ' + isSafari + '
'; output += 'isOpera: ' + isOpera + '
'; output += 'isIE: ' + isIE + '
'; output += 'isIE Edge: ' + isEdge + '
'; document.body.innerHTML = output;

82
задан Lundin 14 May 2019 в 10:34
поделиться

6 ответов

Мне было любопытно на предмет этого так, я записал следующую тестовую программу и скомпилировал ее с g ++ версия 4.1.2.

include <iostream>
#include <string>

using namespace std;

class test
{
public:
        test(const char *name)
                : _name(name)
        {
                cout << _name << " created" << endl;
        }

        ~test()
        {
                cout << _name << " destroyed" << endl;
        }

        string _name;
};

test t("global variable");

void f()
{
        static test t("static variable");

        test t2("Local variable");

        cout << "Function executed" << endl;
}


int main()
{
        test t("local to main");

        cout << "Program start" << endl;

        f();

        cout << "Program end" << endl;
        return 0;
}

, результаты не были тем, что я ожидал. Конструктора для статического объекта не вызывали до первого раза была вызвана функция. Вот вывод:

global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed
81
ответ дан Adam Pierce 24 November 2019 в 09:11
поделиться

Некоторая соответствующая формулировка из Стандарта C++:

3.6.2 Инициализаций нелокального [basic.start.init]

1

объектов устройство хранения данных для объектов со статической продолжительностью хранения ( basic.stc.static) должно быть инициализировано нулем ( dcl.init), прежде чем любая другая инициализация произойдет. Объекты типов POD ( basic.types) со статической продолжительностью хранения, инициализированной с константными выражениями ( expr.const), должны быть инициализированы, прежде чем любая динамическая инициализация происходит. Объекты объема пространства имен со статической продолжительностью хранения, определенной в той же единице перевода и динамично инициализированной, должны быть инициализированы в порядке, в котором их определение появляется в единице перевода. [Отметьте: dcl.init.aggr описывает порядок, в котором инициализируются совокупные участники. Инициализация локальных статических объектов описана в stmt.dcl.]

[больше текста ниже добавления большего количества свобод для разработчиков компилятора]

6.7 операторов объявления [stmt.dcl]

...

4

нулевая инициализация ( dcl.init) всех локальных объектов со статической продолжительностью хранения ( basic.stc.static) выполняется, прежде чем любая другая инициализация происходит. Локальный объект типа POD ( basic.types) со статической продолжительностью хранения, инициализированной с константными выражениями, инициализируется, прежде чем ее блок сначала вводится. Реализации разрешают выполнить раннюю инициализацию других локальных объектов со статической продолжительностью хранения при тех же условиях, что реализации разрешают статически инициализировать объект со статической продолжительностью хранения в объеме пространства имен ( basic.start.init). Иначе такой объект инициализируется, первый контроль времени проходит через свое объявление; такой объект считают инициализированным после завершения его инициализации. Если выходы инициализации путем выдачи исключения, инициализация не завершена, таким образом, ее попробуют еще раз, следующий контроль времени вводит объявление. Если управление повторно вводит объявление (рекурсивно), в то время как объект инициализируется, поведение не определено. [ Пример:

      int foo(int i)
      {
          static int s = foo(2*i);  // recursive call - undefined
          return i+1;
      }

- пример конца ]

5

деструктор для локального объекта со статической продолжительностью хранения будет выполняться, если и только если переменная была создана. [Отметьте: basic.start.term описывает порядок, в котором уничтожаются локальные объекты со статической продолжительностью хранения.]

48
ответ дан Jason Plank 24 November 2019 в 09:11
поделиться

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

24
ответ дан genpfault 24 November 2019 в 09:11
поделиться

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

@Adam: Это негласно инжекция кода компилятором является причиной результата, который Вы видели.

10
ответ дан Henk 24 November 2019 в 09:11
поделиться

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

Статические переменные в функциональном объеме рассматривают то же, обзор является просто конструкцией уровня языка.

Поэтому Вам гарантируют это, статическая переменная будет инициализирована к 0 (если Вы не определите что-то еще), а не неопределенное значение.

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

В C++ (глобально ограниченный по объему) статическим объектам вызвали их конструкторов как часть запуска программы под управлением библиотеки времени выполнения C. Под Visual C++, по крайней мере, порядком, в котором инициализируются объекты, можно управлять прагма init_seg .

3
ответ дан Rob Walker 24 November 2019 в 09:11
поделиться

Или это инициализируется, когда doSomething () сначала называют?

Да, это. Это, среди прочего, позволяет Вам инициализировать глобально полученные доступ структуры данных, когда это является соответствующим, например, в блоках попытки/выгоды. Например, вместо

int foo = init(); // bad if init() throws something

int main() {
  try {
    ...
  }
  catch(...){
    ...
  }
}

можно записать

int& foo() {
  static int myfoo = init();
  return myfoo;
}

и использовать его в блоке попытки/выгоды. На первом вызове будет инициализирована переменная. Затем на первых и следующих вызовах его значение будет возвращено (ссылкой).

3
ответ дан Jason Plank 24 November 2019 в 09:11
поделиться
Другие вопросы по тегам:

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