Каждое имя в языке C++ (за исключением имен препроцессора; см. раздел A.17) имеет определенную область видимости (scope); иначе говоря, существует область текста, в которой его можно использовать. Данные (объекты) хранятся в памяти; вид памяти, используемой для хранения объекта, называется классом памяти (storage class). Время жизни (lifetime) объекта отсчитывается от момента его инициализации до момента окончательного уничтожения.
<p id="AutBody_Root583"><strong>A.4.1. Область видимости</strong></p>Существует пять видов областей видимости (см. раздел 8.4).
• Глобальная область видимости (global scope). Имя находится в глобальной области видимости, если оно объявлено вне языковой конструкции (например, вне класса или функции).
• Область видимости пространства имен (namespace scope). Имя находится в области видимости пространства имен, если оно определено в пространстве имен и вне какой-либо языковой конструкции (например, вне класса и функции). Формально говоря, глобальная область видимости — это область видимости пространства имен с “пустым именем”.
• Локальная область видимости (local scope). Имя находится в локальной области видимости, если она объявлена в функции (включая параметры функции).
• Область видимости класса (class scope). Имя находится в области видимости класса, если оно является именем члена этого класса.
• Область видимости инструкции (statement scope). Имя находится в области видимости инструкции, если оно объявлено в части (...
) инструкции for
, while
, switch
или if
.
Область видимости переменной распространяется (исключительно) до конца инструкции, в которой она объявлена. Рассмотрим пример.
for (int i = 0; i
// переменная i может быть использована здесь
}
if (i < 27) // переменная i из инструкции for вышла из области
// видимости
Области видимости класса и пространства имен имеют свои имена, поэтому можем ссылаться на их членов извне. Рассмотрим пример.
void f(); // в глобальной области видимости
namespace N {
void f() // в пространстве области видимости N
{
int v; // в локальной области видимости
::f(); // вызов глобальной функции f()
}
}
void f()
{
N::f(); // вызов функции f(x) из области видимости N
}
Что произойдет, если мы вызовем функции N::f()
или ::f()
? См. раздел A.15.
<p id="AutBody_Root584"><strong>A.4.2. Класс памяти</strong></p>Существуют три класса памяти (раздел 17.4).
• Автоматическая память (automatic storage). Переменные, определенные в функциях (включая параметры функции), размещаются в автоматической памяти (т.е. в стеке), если они явно не объявлены с помощью ключевого слова static
. Автоматическая память выделяется, когда функция вызывается, и освобождается при возвращении управления в вызывающий модуль. Таким образом, если функция (явно или неявно) вызывает сама себя, может существовать несколько копий автоматических данных: по одной копии на каждый вызов (см. раздел 8.5.8).
• Статическая память (static storage). Переменные, объявленные в глобальной области видимости и в области видимости пространства имен, хранятся в статической памяти, как и переменные, явно объявленные с помощью ключевого слова static
в функциях и классах. Редактор связей выделяет статическую память до запуска программы.
• Свободная память (куча) (free store (heap)). Объекты, созданные с помощью оператора new
, размещаются в свободной памяти.
Рассмотрим пример.
vector vg(10); // создается один раз при старте программы
// ("до функции main()")
vector* f(int x)
{
static vector vs(x); // создается только при первом
// вызове f()
vector vf(x+x); // создается при каждом вызове f()
for (int i=1; i<10; ++i) {
vector vl(i); // создается на каждой итерации
// ...
} // переменная v1 уничтожается здесь (на каждой итерации)
return new vector(vf); // создается в свободной памяти
// как копия переменной vf
} // переменная vf уничтожается здесь
void ff()
{
vector* p = f(10); // получает вектор от функции f()
// .. .