статические и внешние переменные - PullRequest
4 голосов
/ 01 июля 2010

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

Ответы [ 2 ]

25 голосов
/ 01 июля 2010

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

Если переменная определена вне функции, она может использоваться всеми функциями в файле.Иногда также называется «глобальной переменной».Это означает, что существует только один экземпляр этой переменной для всего файла.Также имя переменной сохраняется в результирующем файле .OBJ.Последнее важно, так как, если другой файл также определяет переменную с тем же именем вне функции, компоновщик предполагает, что в обоих случаях это одна и та же переменная, и объединяет их.Чтобы сделать это более понятным, лучше всего добавить ключевое слово "extern" к одной из переменных.В этом случае мы говорим, что объявляем переменную, а не определяем ее.Это дополнительный сигнал для компилятора / компоновщика, указывающий, что мы действительно хотим сослаться на глобальную переменную, определенную где-то еще.

Если вы хотите определить глобальную переменную, но не хотите сделать ее доступнойв другие файлы добавьте ключевое слово static перед.Ключевое слово static сообщает компилятору, что имя переменной не должно храниться в файле .OBJ.Это означает, что два файла .C со следующей строкой:

static long MyGlobalVariable;

каждый будет иметь свою собственную переменную.Обе переменные будут называться MyGlobalVariable.

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

void MyFunction()
{
static long MyLocalVariable = 0;
++MyLocalVariable;
}

При первом вызове функции MyLocalVariable будет «создан» и инициализирован значением 0. В концефункция, переменная не уничтожается, но сохраняется.Поэтому в следующий раз, когда вы вызовете эту функцию, значение переменной будет равно 1, а не нулю.

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

В C ++ все совсем по-другому.Если вы напишите это (вне функции):

MyClass MyGlobalVariable;

MyGlobalVariable будет создан (это: конструктор будет выполнен) в начале приложения, до того, как будет вызван даже main.Однако вы не можете реально контролировать порядок, в котором создаются все глобальные переменные.Так что, если другой файл содержит это:

MyOtherClass MySecondGlobalVariable;

Вы не можете точно знать, был ли сначала создан MyGlobalVariable или MySecondGlobalVariable.Это может создать проблемы, если конструктор одного из них зависит от наличия (конструкции) другого.

С другой стороны, если вы определяете переменную как статическую внутри функции:

void MyFunction()
{
static MyClass MyStaticVariable;
}

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

MyClass &getMyClass()
{
static MyClass MySelf;
return MySelf;
}

И мы реализовали синглтон, в котором мы можем контролировать его построение.Первый раз, когда нам это нужно, он создается.

Если честно, этот подход является довольно упрощенным, поскольку он может привести к проблемам в многопоточных приложениях.В этом случае есть и другие хитрости.

0 голосов
/ 02 июля 2010

«Статический» более или менее означает «это будет существовать всегда». В зависимости от контекста вы получите разные результаты:

 static int global_variable;
 void function()
 {
      static int global_function_variable;
 }

 class foo
 {
      static void function()
      {
           static int foo_function_variable;
           //...
      }
      static int foo_variable;
 }

global_variable - Только когда-либо видимый в пределах "единицы перевода". (Поскольку заголовки более или менее копируются, означает ли это, что статический глобал в заголовке существует как отдельные переменные для всех файлов cpp, в которые он включен?)

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

foo::function() - это функция, которая может быть вызвана как глобальная функция; вам не нужно иметь экземпляр foo для его вызова. Это означает, что у него нет действительного указателя this, однако. Точно так же foo_variable существует, даже когда нет объектов foo. Все foo объекты имеют одинаковые foo_variable - если вы измените его в одном объекте, все остальные объекты "увидят" изменение.

foo_function_variable ведет себя, я думаю, так же, как global_function_variable.

Основная идея extern заключается в управлении связью переменной: От MSDN :

// specifying_linkage1.cpp
int i = 1;
void other();

int main() {
   // Reference to i, defined above:
   extern int i;
}

void other() {
   // Address of global i assigned to pointer variable:
   static int *external_i = &i;

   // i will be redefined; global i no longer visible:
   // int i = 16;
}

extern int global_variable;

extern также может использоваться для связывания переменной с использованием другого языка, чаще всего C.

global_variable - наиболее распространенное использование extern; он говорит, что в другом месте есть переменная с именем global_variable, и мы собираемся использовать эту переменную. Где-то вам нужно объявить переменную без ключевого слова extern, иначе она никогда не будет создана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...