4880

Область видимости и время жизни переменных. Локальные и глобальные переменные. Статические переменные

Лекция

Информатика, кибернетика и программирование

Область видимости и время жизни переменных. Локальные и глобальные переменные. Статические переменные. Каждое имя в программе на С++ должно относиться к уникальной сущности –объекту, функции, типу или шаблону. Однако, это не означает, что оно м...

Русский

2012-11-28

49 KB

14 чел.

Область видимости и время жизни переменных. Локальные и глобальные переменные. Статические переменные.

Каждое имя в программе на С++ должно относиться к уникальной сущности –объекту, функции, типу или шаблону. Однако, это не означает, что оно может встретиться только один раз во всей программе: имя можно повторно использовать для обозначения другой сущности, но только в тос случае, когда есть некоторый контекст, позволяющий различить разные значения одного и того же имени. В качестве такого контекста выступает область видимости.

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

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

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

int x;            // глобальное x

void f()

{

   int x;        // локальное x скрывает глобальное x

   x = 1;        // присвоить локальному x

   

   // вложенный блок

   {     

       int x;    // скрывает первое локальное x

       x = 2;    // присвоить второму локальному x

   }

   

   x = 3;        // присвоить первому локальному x

}

int* p = &x;      // взять адрес глобального x

 

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

int x;

void f2()

{

 int x = 1;      // скрывает глобальное x

::x = 2;        // присваивание глобальному x

}

Имена  формальных параметров функции считаются описанными в основном блоке функции, поэтому в описании ниже есть ошибка: x определено дважды в одной и той  же  области видимости:

void f5( int x )

{

 int x;       // ошибка

}

Для некоторых инструкций языка C++ разрешено объявлять переменные внутри управляющей части. Например, в цикле for переменную можно определить внутри инструкции инициализации:

for ( int i = 0; i < 10; ++i )

{

cout << i;

}

cout << i; // ошибка

Поскольку переменная, объявленная в инструкции инициализации цикла for, является локальной для цикла, то же самое имя допустимо использовать аналогичным образом и в других циклах, расположенных в данной локальной области видимости:

void f( int * a, int N )

{

 for ( int i = 0; i < N; ++i )     // допустимо

 a[i] = i;

 for ( int i = N - 1; i >= 0; --i )  // допустимо, другое i

 cout << a[i];

 for ( int i = 0; i < N; ++i )     // допустимо, другое i

 a[i] = a[i] * a[i];

}

Аналогично переменная может быть объявлена внутри условия инструкций if и switch, а также внутри условия циклов while и for.

Объявление функции в глобальной области видимости вводит глобальную функцию, а объявление переменной – глобальный объект. Глобальный объект существует на протяжении всего времени выполнения программы. Время жизни глобального объекта начинается с момента запуска программы и заканчивается с ее завершением. Для того чтобы глобальную функцию можно было вызвать или взять ее адрес, она должна иметь определение. Любой глобальный объект, используемый в программе, должен быть определен, причем только один раз.

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

// объявление функции calc()

// определение находится где-то (в другом файле)

void calc( int );

void main()

{

 int loc1 = get(); // ошибка: get() не объявлена

calc( int );      // допустимо: calc() объявлена

}

Определение объекта имеет две формы:

имя_типа имя_объекта;

имя_типа имя_объекта = начальное_значение;

Например, ниже дано определение obj1. Здесь obj1 инициализируется значением 97:

int obj1 = 97;

Следующая инструкция определяет obj2, хотя начальное значение не задано:

int obj2;

Объект, определенный в глобальной области видимости без явной инициализации,

гарантированно получит нулевое значение. Таким образом, в следующем примере и v1, и v2 будут равны нулю:

int v1 = 0;

int v2;

Глобальный объект можно определить в программе только один раз. Поскольку он

должен быть объявлен в исходном файле перед использованием, то для программы, состоящей из нескольких файлов, необходима возможность объявить объект, не определяя его. Этого можно добиться с помощью ключевого слова extern, аналогичного объявлению функции: оно указывает, что объект определен в другом месте – в этом же исходном файле или в другом. Эта инструкция только «сообщает» комиплятору, что в программе имеется определение; подобное extern-объявление не выделяет места под объект. Оно может встретиться несколько раз в одном и том же исходном файле или в разных файлах одной программы, однако обычно находится в общедоступном заголовочном файле, который включается в те модули, где необходимо использовать глобальный объект. Ключевое слово extern может быть указано и при объявлении функции – для явного обозначения его подразумеваемого смысла: “определено в другом месте”.

// заголовочный файл

extern int v1;

extern int v2;

// исходный файл

int v1 = 55;

int v2;

extern void f( int *, int );

Объявление переменной в локальной области видимости вводит локальный объект. Существует три вида таких объектов: автоматические, регистровые и статические, различающиеся временем жизни и характеристиками занимаемой памяти. Автоматический объект существует с момента активизации функции, в которой он определен, до выхода из нее. Регистровый объект – это автоматический объект, для которого поддерживается быстрое считывание и запись его значения. Локальный статический объект располагается в области памяти, существующей на протяжении всего времени выполнения программы.

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

int * f()

{

 int a = 10;

 return &a; // опасно!

}

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

// Индекс цикла размещен в регистровой памяти

for ( register int i = 0; i < size; ++i )

{...}

Внутри функции можно также объявить объект с локальной областью видимости, который, несмотря на это, будет существовать в течение всего время выполнения программы (т.е. будет иметь время жизни как глобальный). Для этого переменную объявляют с модификатором static (статический). Значение такого объекта будет сохраняться между вызовами функции, в которой он определен, но видимость его имени ограничена локальной областью функции. Статический локальный объект инициализируется только один раз в момент первого выполнения инструкции его объявления. Неинициализированные статические локальные объекты получают значение 0. В следующем примере статическая переменная используется для подсчета количества вызовов функции:

void func()

{

  static int callCount; // инициализируется 0

  callCount++;

std::cout << "Функция вызвана " << callCount << " раз" <<   std::endl;

}


 

А также другие работы, которые могут Вас заинтересовать

26038. Особенности замещение государственных должностей 43.5 KB
  Особенности замещение государственных должностей По действующему законодательству государственные должности государственной службы замещаются путем назначения. Правом на замещение вакантной должности гражданской службы обладают гражданские служащие граждане которые соответствую установленным законодательством Российской Федерации о государственной гражданской службе квалификационным требованиям к вакантной должности. К числу квалификационных требований относятся: требования к стажу государственной службы или стажу работы по специальности...
26039. Цели и задачи реформирования и развития системы государственной службы 50.5 KB
  Цели и задачи реформирования и развития системы государственной службы. Основные цели и задачи реформирования системы государственной службы Российской Федерации были сформулированы в Концепции реформирования системы государственной службы Российской Федерации утвержденной Президентом РФ 15 августа 2001 году. В соответствии с Концепцией созданы основы единой системы гос. В процессе реформирования гос.
26040. Общая структура триггеров 13.24 KB
  Информационные сигналы поступают на входы A и В ЛУ и преобразуются в сигналы поступающие на внутренние входы S и R ЯП. Управляющие сигналы на асинхронный триггер воздействуют непосредственно с началом своего появления на их входах а в синхронных только с приходом сигнала на входе C.
26041. Простые триггеры 20.11 KB
  Схема простейшего триггера построенного на инверторах В этой схеме может быть только два состояния на выходе Q присутствует логическая единица и на выходе Q присутствует логический ноль. Если логическая единица присутствует на выходе Q то на инверсном выходе будет присутствовать логический ноль который после очередного инвертирования подтверждает уровень логической единицы на выходе Q. И наоборот если на выходе Q присутствует логический ноль то на инверсном выходе будет присутствовать логическая единица.
26042. JK-триггеры 14.14 KB
  Подобно RSтриггеру в JKтриггере входы J и K это входы установки выхода Q триггера в состояние 1 или 0. Однако в отличие от RSтриггера в JKтриггере наличие J=K=1 приводит к переходу выхода Q триггера в противоположное состояние. Условие функционирования JKтриггера описывается функцией: Рисунок 51 JKтриггеры: а асинхронные; б тактируемые фронтом. Триггер JKтипа называют универсальным потому что на его основе с помощью несложных коммутационных преобразований можно получить RS и Ттриггеры а если между входами J и K включить...
26043. D-триггеры 13.79 KB
  Характеристическое уравнение триггера: Qn1=Dn. Оно означает что логический сигнал Qn1 повторяет значение сигнала установленное на входе триггера в предшествующий момент времени. Благодаря включению элемента D1 на входы RSтриггера поступают разнополярные сигналы Рисунок 47а поэтому запрещённое состояние входных сигналов исключено но время задержки распространения сигнала элемента D1 должно быть меньше чем у элементов D2 и D3 tзд. В приведённой выше схеме Dтриггера вследствие задержки распространения сигналов сигнал на выходе Q...
26044. Счётные триггеры 18.55 KB
  Функционирование триггера определяется уравнением: Из уравнения следует что Ттриггер каждый раз изменяет своё состояние на противоположное с приходом на счётный вход Т очередного тактирующего импульса длительностью tи. Этому способствует наличие перекрёстных обратных связей с выходов триггера на входы элементов D1 и D2. Для надёжной работы триггера с целью сохранения информации о предыдущем состоянии триггера в момент его переключения в схему вводят элементы задержки имеющие время задержки tз tи. Сигнал на этом входе разрешает при V=1...
26045. Сумматоры, их схемы 98.69 KB
  Сумматоры их схемы В цифровой вычислительной технике используются одноразрядные суммирующие схемы с двумя и тремя входами причём первые называются полусумматорами а вторые полными одноразрядными сумматорами. приведена таблица истинности полусумматора на основании которой составлена его структурная формула в виде СДНФ Основными параметрами характеризующими качественные показатели логических схем являются быстродействие и количество элементов определяющее сложность схемы. Быстродействие определяется суммарным временем задержки сигнала...
26046. Программированные логические матрицы(ПЛЦ) 14.64 KB
  Программированные логические матрицыПЛЦ Основная идея работы ПЛМ заключается в реализации логической функции представленной в СДНФ дизъюнктивной нормальной форме. В схеме ПЛМ приведенной на рисунке 1 ранг терма ограничен количеством входов и равен четырем количество термов тоже равно четырем. В реально выпускавшихся микросхемах программируемых логических матриц ПЛМ количество входов было равно шестнадцати максимальный ранг минтерма 16 количество термов равно 32 и количество выходов микросхемы 8. Следует отметить что полная...