- •Часть 2
- •18 Сентября 2012 г., протокол № 1
- •Предисловие
- •Глава 6 простые типы данных § 1. Целый тип
- •1.1. Битовые операции
- •Использование битовых операций
- •1.3. Упаковка и распаковка информации
- •§ 2. Логический тип
- •§ 3. Символьный тип
- •§ 4. Вещественный тип
- •§ 5. Преобразование типов
- •Преобразование типов в выражениях
- •Преобразование типов при присваивании
- •Г л а в а 7 введение в указатели
- •§ 1. Понятие указателя. Операции разыменования и разадресации
- •§ 2. Инициализация и присваивание указателей
- •§ 3. Распределение динамической памяти
- •Операция new
- •Операция delete
- •§ 4. Параметры-указатели. Функция ввода scanf
- •Упражнения, тесты
- •Г л а в а 8 одномерные массивы, указатели и функции
- •§ 1. Связь указателей и одномерных массивов. Передача массива в качестве параметра функции
- •§ 2. Сортировка одномерных массивов
- •§ 3. Сортировка массива по параметру числа
- •§ 4. Сортировка массива выбором.
- •§ 5. Сортировка массива вставками
- •§ 6. Динамические одномерные массивы
- •6.1. Порядок работы с динамическим массивом
- •6.2. Работа с динамическим массивом в классе. Деструктор
- •§ 7. Введение в строки
- •Глава 9 мАтрицы
- •§ 1. Объявление, способы определения матриц
- •§ 2. Вывод матриц
- •§ 3. Типы алгоритмов
- •3.1. Построчная обработка
- •Обработка матрицы по столбцам
- •3.3. Обработка всей матрицы
- •3.4. Обработка части матрицы
- •Преобразование матрицы
- •Построение матриц
- •§ 4. Матрицы, указатели и функции
- •Упражнения и тесты
- •Обработка матрицы по столбцам.
- •Список реКоМендуемой литературы
- •Сборники задач по программированию
- •Оглавление
- •Методы программирования:
- •Лекции, примеры, тесты
- •Пособие для студентов механико-математического факультета
- •В двух частях
- •Часть 2
Операция delete
Операция используется для явного освобождения выделенного операцией new участка памяти. В нашем случае её синтаксис такой: delete указатель;.
Для предыдущего примера delete p; освобождает ячейку, адрес которой хранился в переменной-указателе (p). Но при этом ячейка p, в которой находится адрес вещественного числа, из памяти не удаляется и её можно продолжать использовать. Но значение и p, а, значит, и *p, после выполнения операции не определено.
Операцию delete необходимо использовать только для указателя, получившего значение с помощью new. Например, если float x; float *q=&x;, то результат операции delete q; непредсказуем.
Нельзя использовать эту операцию и для статического массива. Следующий код const n=10; int a[n]; … delete a; приводит к ошибке!
§ 4. Параметры-указатели. Функция ввода scanf
Мы уже знаем два способа передачи параметров (не массивов) в функцию: передача по значению и по ссылке. Когда полученное или изменённое в функции значение необходимо возвратить в вызывающую функцию, можно использовать третий способ передачи параметра: с помощью указателя.
Для повторения и сравнения приведём все три способа передачи параметров.
Пример 1. /* 1) В первой функции MyMax1 рассматривается передача параметров с помощью указателей. Изменённые значения с их помощью возвращаются из MyMax1 в вызвавшую её функцию. Обратим внимание, что в тексте функции для доступа к числам, находящимся в ячейках с адресами x и у, необходимо использовать операцию разадресации. */
void MyMax1 (int* x, int* y)
{ if (*x>*y) { int t=*x; *x=*y; *y=t; } }
/* 2) Передача параметров с помощью ссылочного типа (повторение). */
void MyMax2 (int &x, int &y)
{ if (x>y) { int t=x; x=y; y=t; } }
/* 3) При передаче параметров по значению (повторение) изменённые значения не возвращаются из функции в вызвавшую её функцию. */
void MyMax3 (int x, int y)
{ if (x>y) { int t=x; x=y; y=t; } }
/* В последних двух вариантах в тексте функции никакие операции над указателями (ни *, ни &) не используются, так как x и y — не указатели.
Вызов функций зависит от того, работаем мы с простыми переменными или с указателями. */
int main()
{ /* Первый вариант вызова функций. Используем не указатели, а “простые” обычные переменные (a и b). */
int a, b; cout<<"Two int numbers"<<endl;
/* Стандартная функция для ввода scanf и “наша” функция MyMax1 в качестве формальных параметров использует указатели. Поэтому в качестве фактических параметров в функцию передаём &a и &b, (адреса переменных a и b.) */
scanf("%d %d", &a, &b); MyMax1(&a, &b);
cout<<"a = "<<a<<"; b = "<<b<<endl;
/* Если ввели, например, 5 и 2, то выведем a = 2; b = 5. Почему? В x передаётся &a — адрес ячейки a. Поэтому a в main и *x в MyMax1 (аналогично b в main и *y в MyMax1) — это одни и те же ячейки памяти, только по-разному называются. */
scanf("%d %d", &a,&b); MyMax2(a,b);
cout<<"a = "<<a<<"; b = "<<b<<endl;
/*Аналогично, если ввели, например, 5 и 2, то выведем a = 2; b = 5, так как a в main и x в MyMax2 (b в main и y в MyMax2) — это одни и те же ячейки памяти, только по-разному называются. */
scanf("%d %d", &a,&b); MyMax3(a,b);
cout<<"a = "<<a<<"; b = "<<b<<endl;
/* Здесь a и b не изменились после выполнения функции, так как a в main и x в MyMax3 (b и y) — это разные ячейки памяти.
Второй вариант вызова функций. Используем указатели, значения которых надо не забыть проинициализировать. */ int* p1=new int; int* p2=new int;
/* Так как функции scanf и MyMax1 требуют, чтобы были переданы адреса, то при их вызове операция разадресации не используется. А поскольку, кроме этого, переменные объявлены как указатели, то при вызове не используем и операцию & (взятие адреса). Переменные p1 и p2 уже являются адресами без этой операции. Поэтому вызов будет таким: */
scanf ("%d %d", p1, p2); MyMax1(p1, p2);
/* Наоборот, при работе с ячейками, адреса которых в p1 и в p2, надо не забыть использовать операцию разадресации. Без неё были бы выведены адреса, а не числа, с которыми мы работаем. */
cout<<endl<< "*p1="<<(*p1) << "; *p2="<<(*p2);
scanf ("%d %d",p1,p2);
/* Так как функции MyMax2 и MyMax3 в качестве параметров адреса не используют, то в качестве фактических параметров должны записать содержимое ячеек p1 и p2, которое получается как результат операции разадресации (*). */
MyMax2(*p1,*p2); cout<<endl<<"*p1="<<(*p1) <<"; *p2="<<(*p2);
scanf ("%d %d",p1,p2); MyMax3 (*p1,*p2);
cout<<endl<<"*p1="<<(*p1) <<"; *p2="<<(*p2);
getch(); return 0; }
