Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Відповіді на питання по мові С++по лекціям.docx
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
265.22 Кб
Скачать

1. Змінна і змінна показника.

Змінна updates типа int і змінна-показник p_updates – це дві сторони однієї монети. Оскільки p_updates вказує на адресу updates, *p_updates (тип) і p_updates (показник адреси) повністю еквівалентні.

Об’ява показника повинна спеціфініцировати тип даних вказаного значення. Наприклад: int *p_updates; Цей оператор вказує, що комбінація *p_updates має тип int.

Зверніть увагу, що змінні різних типів мають рівні розміри комірок пам’яті, а показник адреси має один розмір комірки пам’яті. Коли ви створюєте показник на С++, то комп’ютер для зберігає адреси для пам’яті, на який вказує адрес. Резервування місця для даних виконується окремим кроком.

Золоте правило показника: завжди ініціалізувати показник, щоб визначити адрес, перш ніж звернутися до нього з використанням операції *(разименованія).

2. Що таке змінні та показники.

Показники – це не типи цілих чисел, хоча комп’ютери виражають адреси цілими числами. Показники не мають сенсу виконувати арифметичні операції між собою.

Змінні – це іменована область, що виділена при компіляції. У мові С++ пропонується спосіб – операція new. Ви повідомляєте new, для даних якого типу запрошується пам’ять. Операція new знаходить блок пам’яті потрібного розміру і повертає його адресу. Ви присвоюєте цій адрес показнику.

  1. Звільнення пам’яті.

Операція delete дозволяє повернути після завершення програми пам’ять у пул (блок) вільної пам’яті. Пам’ять, яку ви звільняєте, потім повторно може бути використана іншими блоками програми. Наведемо приклад:

int *ps = new int; //виділення пам’яті операцією new для використання

…….

delete ps; //звільнити пам'ять операцією delete, коли вона не потрібна

Зверніть увагу, що обов’язковою умовою застосування операції delete є використання її з пам’яттю, яка виділена операцією new.

  1. Важливі обставини відносно динамічних масивів.

Розглянемо дві важливі обставини відносно динамічних масивів: як використати операцію new для створення масиву і як використати показник для доступу до його елементів.

Використовуючи new і delete, повинні дотримуватися наступних правил:

  1. Не використовувати delete для звільнення тієї пам’яті, котра не була виділена new.

  2. Не використовувати delete для звільнення одного й того ж блока пам’яті двічі.

  3. Використовувати delete [], коли для розміщення масиву застосовувався new [ ].

  4. Використовувати delete (без дужок), коли застосовувався new для розміщення окремого елементу.

  5. Безпечно застосовувати delete до нульового показника.

Оператор

int *psome = new int [10]; //отримати блок для 10 елементів типу int

створює показник psome, який вказує на перший елемент блока із 10 значень int.

5. Як зробити доступ до кожного елемента масиву?

Операція new постачає інформацію потрібну для ідентифікації кожного елемента в блоці. Щоб отримати доступ до кожного елемента достатньо для першого елемента написати psome [0], для другого psome [1] і так далі. Еквівалентність застосування індексів у масивах та показниках є важливо. Особливості для мов С і С++ полягають у тому, що внутрішню вони працюють з масивами через показники.

  1. Яка різниця між показниками та іменами масивів?

Спорідненість показників та імен масивів відбувається із арифметики показників, а також як С++ працює з масивами. Додавання 1 до змінної цілих чисел збільшує її значення на одиницю, але додавання 1 до змінної показника збільшує його значення на декілька байт, які складають розмір того типу, на який вона вказує. Додавання 1 до показника double додає 8 байт до числовій величини показника, в той час як додавання 1 до показника short додає 2 байта.

ЛЕКЦІЯ 10.

  1. Об’ява показників та присвоєння ім значень.

 Об’ява показників

double * pn; // pn може вказувати на значення double

char * pс; // pс може вказувати на значення char

Присвоєння значень показникам

Показникам потрібно присвоювати адреси пам’яті. Для цього можна застосовувати операцію & до імені змінної, щоб отримати адрес іменованої області пам’яті, або операцію new, котра повертає адресу іменованій пам’яті.

double * pn; // pn може вказувати на значення double

double * pа; // pа може вказувати на значення double

char * pс; // pс може вказувати на значення char

double bubble = 3.2;

pn = &bubble; //присвоїти адрес bubble змінної pn

pс = new char; //присвоїти адрес виділеної пам’яті char змінної pс

pа = new double [30]; // присвоїти адрес масиву із 30 double змінної pа

  1. Разименованія показників

Разименованія показника означає отримання значення, на котре він вказує. Для цього до показника застосовується операція (*). Тобто, коли pn – показник на bubble, як у попередньому прикладі, то *pn – значення, на яке він вказує, тобто у даному випадку – 3.2.

cout <<*pn; //друк значення bubble

*pс = ‘S’; // помістити ‘S’ в область пам’яті, на яку вказує pс

Нотація масивів – другий спосіб разименованія показника. Наприклад, pn [0] – теж саме, що *pn. Ніколи не слід робити разименованія показника, який не був ініціалізовний вірним адресом.

  1. Різниця між показником і значенням, що вказується

Пам’ятайте, коли pt – показник на int, то *pt – це не показник на int, а повний еквівалент змінної типа int.

int *pt = new int; //присвоювання адреси змінної pt

*pt = 5; //збереження 5 по цій адреси

  1. Імена масивів.

У С++ ім’я масиву трактується як еквівалент адреси його першого елементу.

int tacos [10]; // tacos – теж саме, що &tacos [0]

Винятком з цього правила є застосування операції sizeof до імені масиву. У цьому випадку sizeof повертає розмір усього масиву у байтах.

  1. Арифметика показників

int tacos [10] = {5, 2, 8, 4, 1, 2, 2, 4, 6, 8};

int *pt = tacos; // припустимо, що pt і tacos вказують на адрес 3000

pt = pt + 1; //зараз pt дорівнює 3004, коли int має розмір 4 байта

int *pe = &tacos [9]; // pe дорівнює 3036, коли int має розмір 4 байта

pe = pe – 1; //зараз pe дорівнює 3032 – адрес елемента tacos [8]

int diff = pe – pt; //різниця дорівнює 7, тобто віддалі між tacos [8] і tacos [1]

  1. Динамічне і статичне зв’язування масивів.

Для створення масиву зі статичним зв’язуванням можна використати об’яву масиву –тобто, масиву, чий розмір фіксований на етапі компіляції.

int tacos [10]; // статичне зв’язування, розмір фіксований у час компіляції

Для створення масиву з динамічним зв’язуванням (динамічного масиву) використовується операція new []. Пам’ять для цього масиву виділяється у відповідності з розміром, що вказаний у час виконання програми. Коли робота з таким масивом завершена, то виділена йому пам’ять звільняється операцією delete []:

int size;

cin>> size;

int *pz = new int [size]; // динамічне зв’язування, розмір

//встановлюється у час виконання програми

delete [] pz; // звільняється пам’ять по закінченню роботи з масивом

  1. Нотація масивів та нотація показників.

Використання нотації масивів з квадратними дужками еквівалентно разименованія показника:

tacos [0] визначає *tacos і визначає значення, що знаходиться по адресу tacos

tacos [3] визначає*(tacos + 3) і визначає значення, що знаходиться по адресу tacos + 3

Це справедливо як для імен масивів, так і для змінніх-показників тому, що можна використовувати обидві нотації.

int *pt = new int [10]; // pt вказує на блок із 10 int

*pt = 5; //присвоює елементу 0 значення 5

pt [0] = 6; // присвоює елементу 0 значення 6

pt [9] = 44; // присвоює елементу 10 значення 44

int coats [10];

*(coats + 4) = 12; //встановлює coats [4] значення 12

  1. Показники та рядки.

С об’єктом cout, як і в більшості інших виразів С++, ім’я масиву (наприклад, char), показник на char, а також рядкова константа у лапках – усі вони інтерпретуються як адреса першого символу рядка.

Коли ви читаєте рядок у програмі, то завжди повинні використовувати адресу раніше розподіленої пам’яті. Цей адрес може мати форму імені масиву або показника, який ініціалізовний операцією new.

Для копіювання рядка у масив застосовуйте strcpy () або strncpy (), а не операцію присвоєння.

  1. Використання new для створення динамічних структур

Динамічні визначають виділення пам’яті у час виконання, а не у час компіляції. Застосування new з структурами складається з двох частин: створення структури і звернення до їх членів. Щоб створити структуру, то використовуйте тип структури з операцією new. Щоб створити без імені структуру типу inflatable та присвоїти її адресу відповідному показнику, можна поступити таким чином:

inflatable * ps = new inflatable;

Це присвоїть показнику ps адрес ділянки пам’яті достатньої величини, щоб вмістити тип inflatable.

Більш складна частина – доступ до членів. У С++ передбачена спеціальна операція для цієї ситуації – операція членства через показник (->).

  1. Нотація, копіювання рядка, налагодження розміру сховища для рядка.

Ця операція значить для показників на структуру те, що і операції з точкою для імен структур. Наприклад, коли ps вказує на структуру типу inflatable, то ps->price визначає член price структури, на яку вказує ps.

Щоб отримати копію рядка, потрібно: по-перше, розподілити пам’ять для збереження копії рядка. Це можна зробити або об’явив ще один масив, або використовуючи new. Другий підхід дозволяє точно налагодити розмір сховища для рядка:

ps = new char{strlen(animal) + 1]; //отримати нове сховище

Рядок не повністю заповнює масив animal, тому такий підхід даремно витрачає пам’ять. Тут же ми бачимо використання strlen () для знаходження довжини рядка, а потім до знайденої довжини додаємо 1, щоб отримати довжину, яка б включала нульовий символ. Далі програма застосовує new для виділення достатнього простору для збереження рядка