Выбрать главу

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

После возврата из функции child( ) продолжается выполнение подпрограммы parent( ), и в следующей строке объявляется переменная intLater, которая имеет область видимости, ограниченную функцией parent( ). В момент возврата в функцию main( ) переменные intLater и intParent выходят из области видимости и уничтожаются.

Кроме локальных переменных, программист может объявлять переменные вне всех функций. Такие переменные называются глобальными, они доступны из любого места программы ( их область видимости — вся программа ).

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

Проблемы области видимости...114

Приведённый ниже фрагмент программы будет скомпилирован, но не будет корректно работать.

    double* child( void )

    {

          double dLocalVariable ;

          return &dLocalVariable ;

    }

    void parent( void )

    {

          double* pdLocal ;

          pdLocal = child( ) ;

          *pdLocal = 1.0 ;

    }

_________________

114 стр. Часть 2. Становимся функциональными программистами

Проблема в том, что переменная dLocalVariable объявлена внутри функции child( ). Следовательно, в момент возврата адреса dLocalVariable из child( ) самой переменной уже не существует и адрес ссылается на память, которая вполне может быть занята для каких-то других целей.

«Ошибки подобного типа встречаются довольно часто, а способы их появления весьма разнообразны. К сожалению, такой тип ошибки пропускается компилятором и зачастую не вызывает аварийной остановки программы. Программа может отлично работать большую часть времени, пока память, которая в прошлом выделялась под dLocalVariable, не будет выделена другой переменной. Труднее всего найти ошибки, проявляющиеся спонтанно.» 

[Атас!]

Использование блока памяти...115

Ошибки области видимости возникают потому, что С++ освобождает выделенную для локальных переменных память автоматически. Для решения этой проблемы необходим блок памяти, контролируемый непосредственно программистом. В этом блоке можно выделять память под переменные и удалять их независимо от того, что по этому поводу "думает" С++. Такой блок памяти называется кучей ( heap ).

Память в куче можно выделить, используя оператор new ; он пишется вместе с типом объекта, под который нужно выделить память. Приведённый ниже пример выделяет из кучи память для переменной типа double.

    double* child( void )

   {

         double* pdLocalVariable = new double ;

         return pdLocalVariable ;

    }

Теперь, несмотря на то что переменная pdLocalVariable имеет область видимости в пределах функции child( ), память, на которую указывает эта переменная, не будет освобождена после выполнения функции. Выделение и освобождение памяти в куче осуществляется только явно. Освобождение памяти в куче выполняется с помощью команды delete.

      void parent( void )

      {

           /* функция child( ) возвращает адрес переменной в куче */

           double* pdMyDouble = child( ) ;

           /* сохранение значения в созданной переменной */

           *pdMyDouble = 1.1 ;

           // ...