Еще о классе памяти

Каждая переменная и функция в базовом языке С++ имеет два атрибута: тип и класс памяти. Класс памяти специфицирует способ (как и где) хранения переменной в памяти и время “жизни” переменной.

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

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

Следующий пример использует статическую переменную для Еще о классе памяти генерации последовательности псевдо-случайных чисел. Алгоритм генерации случайных чисел таков:

Выбираем два целых числа a и m, называемых множителем и модулем, соответственно. Начинаем с выбора числа, называемого источником (seed), которое считаем нулевым членом последовательности r[0]. Тогда следующее число рекуррентно вычисляется из предыдущего по формуле

r[n + 1] = a * r[n] mod m.

Например, пара обычно используемых значений - m = 231 -1 = 2147483647, и a = 75 = 48271. Для того, чтобы избежать переполнения, формула слегка модифицируется:

r[n + 1] = a * (r[n] % m) - r * (r[n] / m).

если r[n + 1] < 0, то r[n + 1] = r[n + 1] + m.

Этот алгоритм генерирует случайные числа в диапазоне от 0 до m - 1. Если мы будем брать остатки от Еще о классе памяти деления этих чисел на n, то получим последовательность случайных чисел в пределах от 0 до n - 1.

//Пример 2-1

#include

long int random_number(long seed)

{

const long module = 2147483647L;

const long multiplier = 48271L;

const long quotient = module / multiplier; // = 44488

const long remainder = module % multiplier; // = 3399

static long ran = seed;

// начальное значение испольхуется только в первый раз

ran = (ran % quotient) * multiplier - (ran / quotient) * remainder;

if (ran < 0) { ran = ran + module; }

return ran;

}

int main( )

{

long int seed;

cout << "Enter the seed value.\n";

cin >> seed;

cout << "10 random numbers between 0 and 100 are:\n";

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

{ cout << random_number(seed) % 100 << " "; }

return 0;

}

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

//Пример 2-2

#include

int f()

{

static int called = 0;

++called;

return called;

}

main()

{

int call_times;

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

call_times = f();

cout << "\nThe function is called " << call_times << " times\n";

}

Глобальные переменные также могут быть определены как статические (static). Тогда к ним возможен доступ только в том исходном файле, где они объявлены. В других файлах нельзя использовать extern для доступа к ним. В применении к функциям это свойство полезно при разработке закрытых модулей определения функций.

Переменная может быть объявлена как регистровая ( register). Это ключевое слово “предлагает” хранить переменную в Еще о классе памяти регистре процессора (для скорости). Но это не обязательное требование для компилятора. Невозможно получить адрес регистровой переменной.

(4) Константная 'переменная'

Перемення может быть специфицирована как константа с помощью модификатора const. Константная переменная при определении должна быть инициализирована. Она является l-value, но не может быть модифицирована. 'const'- типы и обычные одноименные типы не совместимы, но константная переменная может быть присвоена переменной с соответствующим обычным типом – компилятор осуществит неявное преобразование типов.



Имеются два вида указателей, связанных с константными переменными: константные указатели и указатели на константу:

Константный указатель должен быть инициализирован при определении и не может быть, в дальнейшем, изменен. Но он может быть Еще о классе памяти присвоен обычному указателю.

Указатель на константу не допускает модификацию объекта, на который он указывает, через этот указатель. Указатель на константу не может быть присвоен обычному указателю, но обычный указатель может быть присвоен указателю на константу (но зачем?).

Константный указатель на константу естьодновременно константный указатель и указатель на константу, т.е. это неизменяемый адрес неизменяемой величины

//Пример 2-3:

int main( )

{

const int x = 2, y = 3; // две целых константы

int z = 3;

const int * pc = &x; // указатель на константу

int * const cp = &z; // константный указатель

const int * const cpc = &y; // константный указатель на константу

int * pp = &z;

// x = y; // неверно, константе присвоить ничего нельзя

pc = &z; // OK, указатель на константу может Еще о классе памяти указывать на int

pc = pp; // OK

// pp = &x; // неверно, константный int нельзя превратить в int

// pp = pc; // неверно, константный int нельзя превратить в int

pp = cp; // OK, константный указатель на int преобразуется в

// указатель на int

// *pc = y; // неверно, присваивание константе

z = 5; // OK

z = x; // OK, тип константы x преобразуется в int

// *pc = 5; // неверно, присваивание константе

*cp = x; // OK, присваивание указателю

// cp = &x; // неверно, переадресация константного указателя

// cpc = &x; // неверно, переадресация константного указателя

// *cpc = x; // неверно, присваивание константе

return 0;

}


documentasgsczh.html
documentasgskjp.html
documentasgsrtx.html
documentasgszef.html
documentasgtgon.html
Документ Еще о классе памяти