Язык программирования C++. Вводный курс

Статические локальные объекты


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

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

#include <iostream>

int traceGcd( int vl, int v2 )

{

    static int depth = 1;

    cout << "глубина #" << depth++ << endl;

    if ( v2 == 0 ) {

        depth = 1;

        return vl;



    }

    return traceGcd( v2, vl%v2 );

}

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

#include <iostream>

extern int traceGcd(int, int);

int main() {

    int rslt = traceCcd( 15, 123 );

    cout << "НОД (15,123): " << rslt << endl;

    return 0;

}

Результат работы программы:

глубина #1

глубина #2

глубина #3

глубина #4

НОД (15,123): 3

Неинициализированные статические локальные объекты получают значение 0. А автоматические объекты в подобной ситуации получают случайные значения. Следующая программа иллюстрирует разницу инициализации по умолчанию для автоматических и статических объектов и опасность, подстерегающую программиста в случае ее отсутствия для автоматических объектов.

#include <iostream>

const int iterations = 2;

void func() {

    int value1, value2; // не инициализированы

    static int depth;   // неявно инициализирован нулем

    if ( depth < iterations )

        { ++depth; func(); }

    else depth = 0;

    cout << "\nvaluel:\t" << value1;

    cout << "\tvalue2:\t" << value2;

    cout << "\tsum:\t" << value1 + value2;

}

int main() {

    for ( int ix = 0; ix < iterations; ++ix ) func();

    return 0;

}

Вот результат работы программы:

valuel:  0           value2:  74924      sum:  74924

valuel:  0           value2:  68748      sum:  68748

valuel:  0           value2:  68756      sum:  68756

valuel:  148620      value2:  2350       sum:  150970

valuel:  2147479844  value2:  671088640  sum:  -1476398812

valuel:  0           value2:  68756      sum:  68756

value1 и

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

рекурсивно вызывает сама себя только дважды.



Содержание раздела