Similar presentations:
Информационные технологии. Часть 2. Тема 8. Указатели и массивы. Динамические массивы
1.
Санкт-Петербургский государственныйархитектурно-строительный университет
кафедра информационных технологий
Информационные технологии. Часть 2
Тема 8
Указатели и массивы. Динамические массивы
Букунов Сергей Витальевич
к.т.н., доцент, доцент
2.
РАБОТА С МАССИВАМИЧЕРЕЗ УКАЗАТЕЛИ
3.
Основные сведенияИмя массива представляет собой его адрес (адрес первого элемента
массива).
Этот адрес можно записать в указатель.
Таким образом, для доступа к элементам массива можно
использовать как индекс элемента, так и указатель.
Для правильной организации приращения адреса при
перемещениях по массиву при объявлении указателя необходимо
указывать тип данных, которые будут храниться в массиве (int*,
double* и т.д.).
4.
Доступ к элементам массива через указатели5.
Передача массива в функцию через указательРабота с функциями в случае использования указателей строится
по следующей схеме:
в качестве аргумента функции используется указатель;
при вызове функции в качестве аргумента задается имя массива.
6.
Передача одномерного массива в функцию по указателю7.
Передача массива в функцию через указательПоскольку в С++ указатель можно трактовать как имя массива, то
при работе с элементами массива в функциях, аргументом которых
является указатель, можно использовать имя этого указателя, как
имя массива, т.е. использовать обычный доступ к элементам
массива через индекс, а не через операцию разыменовывания
указателя.
8.
Передача двумерного массива в функцию через указательДля передачи в функцию двумерного массива размерностью n × m
в качестве аргумента ей необходимо передать не просто указатель,
а указатель на массив, каждый элемент которого состоит из m
элементов, где m – количество элементов в каждой строке массива
(т.е. количество столбцов).
Синтаксис такого указателя следующий:
int (*ptr) [m];
Для доступа к элементам массива в этом случае используется
обычный синтаксис массива, т.е. указатель трактуется как имя
массива.
9.
Передача двумерного массива в функцию по указателю10.
Передача двумерного массива в функцию по указателю11.
ВЫДЕЛЕНИЕДИНАМИЧЕСКОЙ
ПАМЯТИ
12.
Выделение динамической памяти. Операция newЧаще всего указатели используются для выделения динамической
памяти во время выполнения программы.
Для этого используется ключевая операция new.
Алгоритм выделения динамической памяти следующий:
Вы сообщаете оператору new, для какого типа данных
запрашивается память;
операционная система находит блок памяти нужного размера и
возвращает его адрес;
этот адрес записывается в указатель.
13.
Выделение динамической памяти. Операция newОбщая форма выделения памяти для отдельного объекта данных:
TYPE* pointer = new TYPE; // выделение памяти под один
элемент типа TYPE;
TYPE* pointer = new TYPE [n] // выделение области памяти для
массива из n элементов типа TYPE и присваивание адреса
выделенной области памяти указателю pointer.
14.
Выделение динамической памяти. Операция new15.
Особенности работы с динамической памятьюВ виду того, что память компьютера является ограниченным
ресурсом, попытка выделения памяти с помощью операции new
может оказаться неудачной. В этом случае операция new
генерирует исключение (возвращает значение 0).
В С++ указатель со значением 0 называется NULL-указателем (или
нулевым указателем).
С++ гарантирует, что нулевой указатель никогда не указывает на
допустимые данные, поэтому он часто используется в качестве
признака неудачного завершения операций или функций, которые в
противном случае должны возвращать корректные указатели.
16.
Освобождение динамической памяти. Операция deleteКогда память, выделенная под переменную, больше не нужна, ее
следует освободить для осуществления возможности ее повторного
использования другими частями программы.
Для освобождения выделенной памяти применяется операция
delete.
Общая форма освобождения выделенному отдельному объекту
данных памяти выглядит следующим образом:
delete pointer; // освобождение области памяти, занятую одной
переменной, адрес которой хранится в указателе pointer
delete [ ] pointer; // освобождение области памяти, занятую
массивом, адрес которого хранится в указателе pointer
17.
Освобождение динамической памяти. Операция deleteЕсли не освободить выделенную динамическую память, например,
после выхода из функции, в которой она была выделена, то эта
память остается зарезервированной, несмотря на то, что она
больше не используется (т.к. мы вышли из функции).
Такой эффект часто называют «утечкой памяти».
В некоторых языках программирования, например, в языке Python,
есть специальные системные утилиты, называемые «сборщиками
мусора», которые выявляют такую зарезервированную, но
неиспользуемую память, и автоматически освобождают её.
В языке С++ таких утилит нет, поэтому за освобождением
динамической памяти должен следить сам программист.
18.
Особенности работы с динамической памятьюПри использовании операций new и delete необходимо придерживаться
следующих правил:
операция delete используется только с памятью, выделенной
операцией new;
нельзя использовать операцию delete дважды для освобождения
одного и того же блока памяти;
нельзя использовать операцию [ ] delete для освобождения блока
памяти, выделенного с помощью операции new для одного элемента;
нельзя использовать операцию delete для освобождения блока памяти,
выделенного с помощью операции new для массива элементов;
применение операции delete к нулевому указателю является
безопасным.
19.
Примеры некорректного использования операции deleteint* ps = new int; // корректно
delete ps;
// корректно
delete ps;
// некорректно – нельзя пытаться освободить дважды одну и ту же область памяти
int var = 5; // корректно
int* pi = &var; // корректно
delete pi; // некорректно – память, на которую указывает pi, не была выделена с помощью
операции new
int* ps = new int; // корректно
int* pq = ps;
// корректно
delete pq; // корректно – pq и ps указывают на один и тот же блок памяти, выделенный с
помощью операции new
int* pt = new int; // корректно
delete [ ] pt; // некорректно – эффект не определен; память была выделена под один элемент
типа int
short* ps = new short[500]; // корректно
delete ps; // некорректно – эффект не определен; память была выделена под массив элементов
типа short
20.
ДИНАМИЧЕСКИЕМАССИВЫ
21.
Одномерный динамический массивДля создания одномерного динамического массива достаточно
сообщить операции new тип элементов массива и требуемое
количество элементов.
Пример. Выделение динамической памяти для хранения массива из
10 элементов типа int:
int* pi = new int [10];
Операция new возвращает адрес первого элемента в блоке,
значение которого присваивается указателю pi.
Здесь указатель pi указывает на первый элемент выделенного
массива.
По завершению работы с выделенным блоком памяти необходимо
сбалансировать вызов new соответствующим вызовом delete:
delete [ ] pi;
22.
Примеры работы с динамической памятью23.
Примеры работы с динамической памятьюВопрос: в чем ошибка ?
24.
Примеры работы с динамической памятьюОтвет: перед выводом массива необходимо вернуть указатель на
начало массива.
25.
Примеры работы с динамической памятью26.
Многомерные динамические массивыДля создания многомерных (например, двумерных) динамических
массивов воспользоваться оператором
int** masd = new int [n] [k];
по аналогии с одномерным динамическим массивом нельзя, т.к. в
этом случае возникает ошибка несоответствия указателей.
27.
Двумерный динамический массивДинамический двумерный массив размерностью m × n создается
следующим образом:
1.
Сначала необходимо с помощью операции new выделить
память под массив из m указателей (для m строк). Эта память будет
представлять собой массив (или вектор), элементами которого
будут
являться
указатели,
располагающиеся
в
памяти
последовательно.
2.
После этого необходимо в цикле каждому указателю
присвоить адрес выделенной области памяти размером n, равным
границе массива, т.е. количеству столбцов.
28.
Двумерный динамический массивДинамический двумерный массив существенно отличается от
обычного двумерного массива.
Под обычный двумерный массив при объявлении выделяется
сплошной участок памяти.
Для динамического массива выделенная память не представляет
собой сплошной участок, поскольку она выделяется с помощью
нескольких операций new.
29.
Реализация двумерного динамического массива30.
Реализация двумерного динамического массива31.
РАБОТА СО СТРОКАМИЧЕРЕЗ УКАЗАТЕЛИ
32.
Строки как массивыСтроки – это массивы элементов типа char.
Поэтому доступ к элементам строки аналогичен доступу к
элементам массива.
Однако при работе со строками следует иметь в виду тот факт,
функциональность работы со строками зависит от способа
определения самой строки.
33.
Строки как массивыВопрос: существует ли принципиальное отличие между этими
двумя способами определения строки с точки зрения вывода?
34.
Строки как массивыОтвет: с точки зрения вывода отличий нет.
35.
Строки как массивыВопрос: существует ли принципиальное отличие между этими
двумя способами определения строки с точки зрения посимвольной
работы со строкой?
Какой из операторов компилятор не пропустит и почему?
str1++;
str2++;
36.
Строки как массивыОтвет:
str1 - это имя массива, которое представляет собой по факту
константный указатель, поэтому изменять значение указателя
нельзя;
str2 – это указатель на константу, поэтому значение самого
указателя можно изменять.
37.
Строки как массивыВопрос: что мы увидим на экране ?
38.
Строки как массивыОтвет:
Вывод: строка, определенная через указатель, гораздо более гибка,
чем строка, определенная как массив символов.
39.
Строки как массивыВопрос: Пропустит ли компилятор такой код и что мы увидим на
экране в этом случае ?
40.
Строки как массивыОтвет:
41.
Строки как массивыВопрос: Пропустит ли компилятор такой код и почему ?
42.
Строки как массивыОтвет:
43.
Строки как массивыОтвет: компилятор не пропустит такой код, потому что str – это
указатель на константу типа char.
Поэтому значение переменной, адрес которой хранится в указателе
str (т.е. саму строку) изменить нельзя.
Значение же самого указателя изменить можно, потому что это
переменная.
44.
Передача строк в функциюПередача строк в функцию по указателю осуществляется
аналогично передаче в функцию массивов по указателю.
45.
Передача строк в функциюПередача строк в функцию по указателю осуществляется
аналогично передаче в функцию массивов по указателю.
46.
Массивы строкПоскольку строку можно задать через указатель, то массив строк в
этом случае будет представлять собой массив указателей.
47.
Массивы строкВопрос: пропустит ли компилятор такой код и что мы увидим на
экране в этом случае ?
48.
Массивы строкОтвет:
49.
Массивы строкВопрос: пропустит ли компилятор такой код и что мы увидим на
экране в этом случае ?
50.
Массивы строкОтвет:
51.
Массивы строкВопрос: пропустит ли компилятор такой код и что мы увидим на
экране в этом случае ?
52.
Массивы строкОтвет:
53.
Массивы строкВопрос: пропустит ли компилятор такой код и что мы увидим на
экране в этом случае ?
54.
Массивы строкОтвет:
Каждый элемент массива str – это указатель на константу!
55.
Динамический массив char-строк.56.
Динамический массив char-строк57.
Динамический массив строк типа string58.
Динамический массив строк типа string59.
Санкт-Петербургский государственныйархитектурно-строительный университет
кафедра информационных технологий
Автор:
Букунов Сергей Витальевич
[email protected]