C++ 1, осень 2014: Указатели и ссылки
description
Transcript of C++ 1, осень 2014: Указатели и ссылки
![Page 1: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/1.jpg)
Лекция 3. Массивы, указатели и ссылки
Лекция 3. Массивы, указатели иссылки
Александр Смаль
CS центр24 сентября 2014Санкт-Петербург
http://compscicenter.ru 1/18
![Page 2: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/2.jpg)
Лекция 3. Массивы, указатели и ссылки
Указатели∙ Указатель — это переменная, хранящая адрес некоторой
ячейки памяти.∙ Указатели являются типизированными.
int i = 3; // переменная типа intint * p = 0; // указатель на переменную типа int
∙ Нулевому указателю (которому присвоено значение 0)не соответствует никакая ячейка памяти.
∙ Оператор взятия адреса переменной &.∙ Оператор разыменования *.
p = &i; // указатель p указывает на переменную i*p = 10; // изменяется ячейка по адресу p, т.е. i
http://compscicenter.ru 2/18
![Page 3: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/3.jpg)
Лекция 3. Массивы, указатели и ссылки
Передача параметров по указателюРассмотрим функцию, меняющую параметры местами:
void swap (int a, int b) {int t = a;a = b;b = t;
}
int main() {int k = 10, m = 20;swap (k, m);cout << k << ’ ’ << m << endl; // 10 20return 0;
}
swap изменяет локальные копии переменных k и m.
http://compscicenter.ru 3/18
![Page 4: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/4.jpg)
Лекция 3. Массивы, указатели и ссылки
Передача параметров по указателюВместо значений типа int будем передавать указатели.
void swap (int * a, int * b) {int t = *a;*a = *b;*b = t;
}
int main() {int k = 10, m = 20;swap (&k, &m);cout << k << ’ ’ << m << endl; // 20 10return 0;
}
swap изменяет переменные k и m по указателям на них.
http://compscicenter.ru 4/18
![Page 5: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/5.jpg)
Лекция 3. Массивы, указатели и ссылки
Массивы∙ Массив — это набор однотипных элементов,
расположенных в памяти друг за другом, доступ ккоторым осуществляется по индексу.
∙ C++ позволяет определять массивы на стеке.
// массив 1 2 3 4 5 0 0 0 0 0int m[10] = {1, 2, 3, 4, 5};
∙ Индексация массива начинается с 0, последний элементмассива длины n имеет индекс n - 1.
for (int i = 0; i < 10; ++i)cout << m[i] << ’ ’;
cout << endl;
http://compscicenter.ru 5/18
![Page 6: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/6.jpg)
Лекция 3. Массивы, указатели и ссылки
Связь массивов и указателей∙ Указатели позволяют передвигаться по массивам.∙ Для этого используется арифметика указателей:
int m[10] = {1, 2, 3, 4, 5};int * p = &m[0]; // адрес начала массиваint * q = &m[9]; // адрес последнего элемента
∙ (p + k) — сдвиг на k ячеек типа int вправо.∙ (p - k) — сдвиг на k ячеек типа int влево.∙ (q - p) — количество ячеек между указателями.∙ p[k] эквивалентно *(p + k).
1 2 3 4 5 0 0 0 0 0
p q(p + 2) (q - 4)
http://compscicenter.ru 6/18
![Page 7: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/7.jpg)
Лекция 3. Массивы, указатели и ссылки
ПримерыЗаполнение массива:
int m[10] = {}; // изначально заполнен нулями// &m[0] &m[9]for (int * p = m ; p <= m + 9; ++p )
*p = (p - m) + 1;// Массив заполнен числами от 1 до 10
Передача массива в функцию:
int max_element (int * m, int size) {int max = *m;for (int i = 1; i < size; ++i)
if (m[i] > max)max = m[i];
return max;}
http://compscicenter.ru 7/18
![Page 8: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/8.jpg)
Лекция 3. Массивы, указатели и ссылки
Два способа передачи массиваbool contains(int * m, int size , int value) {
for (int i = 0; i != size; ++i)if (m[i] == value)
return true;return false;
}bool contains(int * p, int * q, int value) {
for (; p != q; ++p)if (*p == value)
return true;return false;
}
1 2 3 4 5 0 0 0 0 0
p qhttp://compscicenter.ru 8/18
![Page 9: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/9.jpg)
Лекция 3. Массивы, указатели и ссылки
Возрат указателя из функции
Функция для поиска максимума в массиве:
int max_element (int * p, int * q) {int max = *p;for (; p != q; ++p)
if (*p > max)max = *p;
return max;}
int m[10] = {...};int max = max_element(m, m + 10);cout << "Maximum = " << max << endl;
http://compscicenter.ru 9/18
![Page 10: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/10.jpg)
Лекция 3. Массивы, указатели и ссылки
Возрат указателя из функции
Функция для поиска максимума в массиве:
int * max_element (int * p, int * q) {int * pmax = p;for (; p != q; ++p)
if (*p > *pmax)pmax = p;
return pmax;}
int m[10] = {...};int * pmax = max_element(m, m + 10);cout << "Maximum = " << *pmax << endl;
http://compscicenter.ru 10/18
![Page 11: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/11.jpg)
Лекция 3. Массивы, указатели и ссылки
Возрат значения через указательФункция для поиска максимума в массиве:
bool max_element (int * p, int * q, int * res) {if (p == q)
return false;*res = *p;for (; p != q; ++p)
if (*p > *res)*res = *p;
return true;}
int m[10] = {...};int max = 0;if (max_element(m, m + 10, &max))
cout << "Maximum = " << max << endl;
http://compscicenter.ru 11/18
![Page 12: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/12.jpg)
Лекция 3. Массивы, указатели и ссылки
Возрат значения через указатель на указательФункция для поиска максимума в массиве:
bool max_element (int * p, int * q, int ** res) {if (p == q)
return false;*res = p;for (; p != q; ++p)
if (*p > **res)*res = p;
return true;}
int m[10] = {...};int * pmax = 0;if (max_element(m, m + 10, &pmax))
cout << "Maximum = " << *pmax << endl;
http://compscicenter.ru 12/18
![Page 13: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/13.jpg)
Лекция 3. Массивы, указатели и ссылки
Недостатки указателей
∙ Использование указателей синтаксически загрязняет код иусложняет его понимание. (Приходится использоватьоператоры * и &.)
∙ Указатели могут быть неинициализированными(некорректный код).
∙ Указатель может быть нулевым (корректный код), азначит указатель нужно проверять на равенство нулю.
∙ Арифметика указателей может сделать из корректногоуказателя некорректный (легко промахнуться).
http://compscicenter.ru 13/18
![Page 14: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/14.jpg)
Лекция 3. Массивы, указатели и ссылки
Ссылки∙ Для того, чтобы исправить некоторые недостатки
указателей, в C++ введены ссылки.∙ Ссылки являются “красивой обёрткой” над указателями:
void swap (int & a, int & b) {int t = b;b = a;a = t;
}
int main() {int k = 10, m = 20;swap (k, m);cout << k << ’ ’ << m << endl; // 20 10return 0;
}
http://compscicenter.ru 14/18
![Page 15: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/15.jpg)
Лекция 3. Массивы, указатели и ссылки
Различия ссылок и указателей∙ Ссылка не может быть неинициализированной.
int * p; // OKint & l; // ошибка
∙ У ссылки нет нулевого значения.
int * p = 0; // OKint & l = 0; // ошибка
∙ Ссылку нельзя переинициализировать.
int a = 10, b = 20;int * p = &a; // p указывает на ap = &b; // p указывает на bint & l = a; // l ссылается на al = b; // a присваивается значение b
http://compscicenter.ru 15/18
![Page 16: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/16.jpg)
Лекция 3. Массивы, указатели и ссылки
Различия ссылок и указателей
∙ Нельзя получить адрес ссылки или ссылку на ссылку.
int a = 10;int * p = &a; // p указывает на aint ** pp = &p;// pp указывает на переменную pint & l = a; // l ссылается на aint * pl = &l; // pl указывает на переменную aint && ll = l; // ошибка
∙ Нельзя создавать массивы ссылок.
int * mp[10] = {}; // массив указателей на intint & ml[10] = {}; // ошибка
∙ Для ссылок нет арифметики.
http://compscicenter.ru 16/18
![Page 17: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/17.jpg)
Лекция 3. Массивы, указатели и ссылки
lvalue и rvalue∙ Выражения в C++ можно разделить на два типа:
1. lvalue — выражения, значения которых являются ссылкойна переменную/элемента массива, а значит могут бытьуказаны слева от оператора =.
2. rvalue — выражения, значения которых являютсявременными и не соответствуют никакойпеременной/элементу массива.
∙ Указатели и ссылки могут указывать только на lvalue.
int a = 10, b = 20;int m[10] = {1,2,3,4,5,5,4,3,2,1};int & l1 = a; // OKint & l2 = a + b; // ошибкаint & l3 = *(m + a / 2); // OKint & l4 = *(m + a / 2) + 1; // ошибкаint & l5 = (a + b > 10) ? a : b; // OK
http://compscicenter.ru 17/18
![Page 18: C++ 1, осень 2014: Указатели и ссылки](https://reader036.fdocuments.net/reader036/viewer/2022073116/548b9a29b4795902748b4620/html5/thumbnails/18.jpg)
Лекция 3. Массивы, указатели и ссылки
Время жизни переменной
Следует следить за временем жизни переменных.
int * foo() {int a = 10;return &a;
}
int & bar() {int b = 20;return b;
}
int * p = foo();int & l = bar();
http://compscicenter.ru 18/18