О локальных и глобальных статических переменных в С++

С++ Primer говорит

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

Являются ли локальные статические переменные отличными от глобальных статических переменных? Другое место, где они объявлены, что еще не так?

void foo () {   
    static int x = 0;
    ++x;

    cout << x << endl;
}

int main (int argc, char const *argv[]) {
    foo();  // 1
    foo();  // 2
    foo();  // 3
    return 0;
}

сравните с

static int x = 0;

void foo () {   
    ++x;

    cout << x << endl;
}

int main (int argc, char const *argv[]) {
    foo();  // 1
    foo();  // 2
    foo();  // 3
    return 0;
}

Ответ 1

Различия заключаются в следующем:

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

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

Ответ 2

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

Ответ 3

Настоящее имя:

static storage duration object.

Глобальные переменные также являются "объектами продолжительности статического хранения". Основное отличие от глобальных переменных:

  • Они не инициализируются до первого использования
    Примечание. Исключение во время строительства означает, что они не были инициализированы и, следовательно, не использовались.
    Таким образом, он повторит попытку в следующий раз, когда будет введена функция.
  • Там видимость ограничена их областью
    (т.е. они не видны вне функции)

Кроме того, они похожи на другие "объекты продолжительности статического хранения".

Примечание. Как и все "статические объекты продолжительности хранения", они уничтожаются в обратном порядке создания.

Ответ 4

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

#include <iostream>

using namespace std;

static int z = 0;

void method1() {
    static int x = 0;
    cout << "X : " << ++x << ", Z : " << ++z << endl;
}

void method2() {
    int y = 0;
    cout << "Y : " << ++y << ", Z : " << ++z << endl;
}

int main() {
    method1();
    method1();
    method1();
    method1();
    method2();
    method2();
    method2();
    method2();
    return 0;
}

выход:

X : 1, Z : 1
X : 2, Z : 2
X : 3, Z : 3
X : 4, Z : 4
Y : 1, Z : 5
Y : 1, Z : 6
Y : 1, Z : 7
Y : 1, Z : 8

Ответ 5

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

Ответ 6

В вашем первом блоке кода x является локальным для функции foo(), что означает, что он создан в foo() и уничтожен в конце функции после cout. Однако во втором блоке x является глобальным, что означает, что область действия x является всей программой. Если вы хотите, чтобы под int main вы могли cout < x < endl, и он будет печатать, однако, в первом блоке он сказал бы, что x не объявлен

Ответ 7

  • Они известны всем функциям программы, тогда как глобальные переменные известны только в ограниченном объеме.
  • Глобальные статические переменные могут быть инициализированы до запуска программы, тогда как локальные статические переменные могут быть инициализированы, так как выполнение достигает точки.