
- •1 Основні відомості про вказівники
- •2. Вказівники та посилання
- •Void function_a (char*, int, short*);
- •Int *pi; /* вказівник-змінна на дані типу int */
- •3. Ініціалізація вказівника
- •4. Розіменування та присвоєння
- •5. Void-вказівник
- •6. Операція пересування вказівника
- •7. Використання вказівників з модифікатором const
- •8. Деактивації дії модифікатора
- •9. Подвійний вказівник
- •10. Вказівники і масиви
- •11. Доступ до ділянок динамічної пам'яті
- •12. Звільнення пам'яті
- •8. Операції з вказівниками
- •Int I, *pi; /* pi –змінна-вказівник */
- •13. Динамічні масиви
- •11. Посилання
- •Лабораторный практикум
- •Вопросы без ответов
- •3 Основні операції над вказівниками
- •4 Багаторівнева непряма адресація
- •5 Операції над вказівниками
- •Void main ()
- •Void main()
- •6 Проблеми, пов'язані з вказівниками
- •Int *х; /* змінній-покажчику 'х' виділена оп, але 'х' не містить значення адреси оп для змінної */
- •Int *х; /* х - ім'я покажчика, він одержав оп*/
- •Void main ()
- •9 Масиви
- •1.9.1 Основні поняття
- •Int а[5]; /* оголошення зовнішнього масиву */ main ()
- •9.2 Оголошення та звертання в одновимірних масивах
- •9.3 Оголошення та звертання до багатовимірних масивів
- •Int а[3][4]; /* а - вказівник-константа */
- •10 Масиви покажчиків
- •10.1 Робота з великими масивами
- •Void main()
- •Int *p[200], I, j; clrscr() ;
- •10.2 Вільні масиви та покажчики
- •11 Символьні рядки
- •11.1 Основні відомості про представлення рядків
- •11.2 Функції роботи з рядками
- •1. Функції введення рядків.
- •2. Функції виведення рядків.
- •14 Лекція №14
- •14.1 Вказівники Лекція № 2 - Вказівники та посилання
- •1.2.1. Вказівники
- •6. Вказівники і масиви
- •6.1. Вказівники і адреси
- •6.2. Вказівники і аргументи функцій
- •6.3. Вказівники і масиви
- •6.4. Адресна арифметика
- •6.5. Вказівники символів і функції
- •6.6. Вказівники – не цілі значення
- •6.7. Багатовимірні масиви
- •6.8. Масиви вказівників (вказівники на вказівники)
- •6.9. Ініціалізація масивів вказівників
- •6.10. Вказівники і багатовимірні масиви
- •6.11. Командний рядок аргументів
- •6.12. Вказівники на функції
- •Посібник для початківця про вказівники
- •6. Вказівники і структуровані програмні змінні
- •9. Вказівники типу far
- •10. Вказівники і динамічні змінні (керування пам'яттю)
- •9. Вказівники типу far
- •10. Вказівники і динамічні змінні (керування пам'яттю)
- •8. Вказівники і динамічні змінні (керування пам'яттю)
- •Void* operator new(size_t t)
- •Void operator delete(void* p)
- •Void main()
11. Доступ до ділянок динамічної пам'яті
Вказівники часто використовують для роботи з динамічною пам'яттю.
Доступ до виділених ділянок динамічної пам'яті (динамічних змінних) можливий тільки через вказівники.
При визначенні вказівника бажано виконати його ініціалізацію (присвоєння початкового значення). Використання неініціалізованого вказівника приводить до помилки.
Ініціалізація вказівника полягає в виділенні ділянки динамічної пам'яті і присвоєння її адреси вказівнику:
int *n= new int; - виділення динамічної пам'яті, достатньої для розміщення величини типу int і запис адреси цієї ділянки в змінну n або int *n; (оголошується вказівник n) n = new int; (виділяється пам'ять для цілого числа і n робиться вказівником на цю пам'ять). Наступний код показує, як виділити пам'ять для величин з плаваючою точкою подвійної точності: double - double *d; d = new double.
int *m=new int (20) - аналогічно попередньому, але з ініціалізацією динамічної змінної значенням 20
int *z=new int [10] - виділення пам'яті для масиву з 10 елементів
Приклад 18
#include <windows.h>
#include <clocale>
#include <stdio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
int *po;
// зробити po вказівником на нове ціле
po = new int;
*po = 25;
printf("Значення *po: %d\n", *po);
system("pause");
}
Скомпілюйте наведений приклад.
Як і чому він так працює? Коли виконується функція main(), виділяється пам'ять і ініціалізується вказівник, щоб він вказував на цю пам'ять. Коли блоку коду завершується, виділена пам'ять залишається недоторканою і вказівник po все ще вказує на неї, тобто, динамічне виділення відрізняється тим, що пам'ять, яка була виділена не звільняється після завершення блоку коду.
З пам'яттю завжди існують складнощі і в даному випадку досить серйозні, але ці складнощі можна з легкістю обійти. Проблема полягає в тому, що не дивлячись на те, що пам'ять, яка була виділена динамічно, залишається недоторканою, вона ніколи не звільняється автоматично. Пам'ять буде залишатися виділеною до тих пір, поки ви не скажете комп'ютеру що вам вона більше не потрібна. Проблема в тому, що якщо ви не скажете системі, що пам'ять вам більше не потрібна, вона буде займати місце, яке, можливо, необхідно іншим додаткам або частинам вашої програми. Зокрема це може призвести до збою системи через використання всієї доступної пам'яті, тому це дуже важливо.
12. Звільнення пам'яті
Звільнення пам'яті, виділеної за допомогою операції new коли вона вам більше не потрібна, робиться дуже просто:
delete po;
При цьому змінна-вказівник зберігається і може ініціалізуватися повторно.
З цим все. Ви повинні бути обережні, оскільки потрібно передавати правильний вказівник, вказівник який вказує саме на ту область пам'яті яку ви виділяли а не на незрозуміле сміття. Спроба звільнити пам'ять (за допомогою delete), яка вже була звільнена небезпечна і може призвести до збою програми. Тому наступний оновлений приклад показує як це робити правильно без даремного витрачання пам'яті:
Приклад 19
#include <windows.h>
#include <clocale>
#include <stdio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
int *po;
// зробити po вказівником на нове ціле
po = new int;
*po = 25;
printf("Значення *po: %d\n", *po);
delete po;
system("pause");
}
Скомпілюйте наведений приклад.
Якщо ви не видалите пам'ять, то отримаєте так званий "витік пам'яті", коли пам'ять поступово витікає і не може бути повернута, поки програма не закриється.
Керуючи динамічними змінними необхідно:
а) явно створювати і знищувати динамічні змінні та об'єкти;
б) для кожного динамічного об'єкта організовувати принаймні один вказівник, який буде забезпечувати доступу до самого об'єкта.
І останнє попередження щодо масивів: якщо ви виділили пам’ять для масиву з використанням оператору new, як показано в наступному прикладі:
int *p;
p = new int[6];
то повинні потім видалити його з допомогою оператора:
delete[] p;
Зверніть увагу на [] після delete. Це повідомляє компілятор про те, що видаляється цілий масив, а не лише один елемент. Ви повинні використовувати цей метод коли мова йде про масив. В результаті ви отримаєте звільнення пам’яті.
Зауваження: ви не повинні звільняти пам’ять, якщо вона виділялась не через new.