Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

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

Напомним основные (предопределенные целиком или базовые, фундаментальные)типы данных | Тип перечисление | Ii) Инициализация указателей | Еще о выражениях | Кратко: for, while, do-while циклы и простые примеры |


Читайте также:
  1. Алгоритм освобождения памяти
  2. Алгоритмы распределения памяти.
  3. Архитектура видеосистемы ПК. Управления видеосистемой. Режимы. Структура видеопамяти
  4. Архитектура и принцип работы часов реального времени RTC и CMOS памяти. Возможности программирования
  5. Блок памяти (БП);
  6. Взаимодействие программ в памяти
  7. Вопрос посвящается светлой памяти ГБОУ ЦДТ «На Псковской» и других незаслуженно уничтоженных осенью 2014 года малых учреждений дополнительного образования.

 

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

Локальные переменные и формальные параметры функций по умолчанию имеют класс памяти 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 <iostream.h>

 

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 <iostream.h>

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;

}


Дата добавления: 2015-11-16; просмотров: 35 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Понятия области видимости идентификатора (и области действия идентификатора) имеют прямое отношение к, так называемым. пространствам имен.| Некоторые операции

mybiblioteka.su - 2015-2024 год. (0.013 сек.)