Розділ №15. Підсумковий тест

  Юрій  | 

  Оновл. 8 Кві 2021  | 

 30

Ще один розділ позаду. Останній підсумковий тест. Пора закріпити пройдений матеріал.

Теорія

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

Семантика копіювання дозволяє копіювати класи за допомогою конструктора копіювання і оператора присвоювання копіюванням.

Семантика переміщення дозволяє класу передавати володіння ресурсами/об’єктом за допомогою конструктора переміщення і оператора присвоювання переміщенням іншому об’єкту (без виконання копіювання).

Розумний вказівник std::auto_ptr застарів і його слід уникати.

Посилання r-value — це посилання, яке ініціалізується значеннями r-values. Посилання r-value створюється з використанням подвійного амперсанда. Пам’ятайте, що писати функції, які приймають в якості параметрів посилання r-value — добре, але повертати посилання r-value — погано.

Якщо ми створюємо об’єкт або виконуємо операцію присвоювання, де аргументом є l-value, то єдине розумне, що ми можемо зробити — це скопіювати l-value. Справа в тому, що не завжди безпечно змінювати l-value, тому що воно ще може бути використане пізніше в програмі. Якщо у нас є вираз a = b, то ми сподіваємося, що b не буде якимось чином змінено пізніше.

Однак, якщо ми створюємо об’єкт або виконуємо операцію присвоювання, де аргументом є r-value, то ми знаємо, що r-value — це всього лише тимчасовий об’єкт. Замість того, щоб копіювати його (що може бути затратно), ми можемо просто перемістити його ресурси (що не дуже затратно) в об’єкт, який створюємо або якому присвоюємо. Це безпечно, оскільки тимчасовий об’єкт в будь-якому випадку буде знищений в кінці виразу, і ми можемо бути впевнені, що він більше ніколи не буде використаний знову!

Ви можете використовувати ключове слово delete для відключення семантики копіювання в створюваних вами класах, видаливши конструктор копіювання і оператор присвоювання копіюванням.

Функція std::move() дозволяє конвертувати l-value в r-value. Це корисно, коли ви хочете використовувати семантику переміщення замість семантики копіювання з аргументом, який з самого початку є l-value.

Розумний вказівник std::unique_ptr — це клас розумного вказівника, який одноосібно володіє переданим йому динамічно виділеним ресурсом. Функція std::make_unique() — це функція, додана в C++14, яку ви повинні використовувати для створення нового std::unique_ptr. У std::unique_ptr семантика копіювання за замовчуванням відключена.

Розумний вказівник std::shared_ptr — це клас розумного вказівника, який слід використовувати, коли потрібно, щоб одним динамічно виділеним ресурсом володіли відразу кілька розумних вказівників. Ресурс не буде знищений до тих пір, поки не буде знищений останній std::shared_ptr, який володіє ним. Для створення нового std::shared_ptr використовуйте функцію std::make_shared(). Для створення додаткового std::shared_ptr, який би вказував на поточний ресурс, ви повинні використовувати семантику копіювання.

Розумний вказівник std::weak_ptr — це клас розумного вказівника, який ви повинні використовувати, коли вам потрібен один або кілька вказівників з можливістю перегляду і доступу до динамічно виділеного ресурсу, яким керує інший std::shared_ptr, але щоб цей вказівник не брав участі в знищенні ресурсу. std::weak_ptr власником ресурсу не рахується.

Тест

Завдання №1

Поясніть, коли слід використовувати наступні типи розумних вказівників:

a) Розумний вказівник std::unique_ptr

Відповідь №1.a)

Розумний вказівник std::unique_ptr слід використовувати, коли потрібно, щоб розумний вказівник одноосібно володів динамічно виділеним ресурсом.

b) Розумний вказівник std::shared_ptr

Відповідь №1.b)

Розумний вказівник std::shared_ptr слід використовувати, коли потрібно, щоб відразу кілька розумних вказівників володіло одним динамічно виділеним ресурсом. Ресурс не буде знищений до тих пір, поки не будуть знищені всі std::shared_ptr, які ним володіють.

c) Розумний вказівник std::weak_ptr

Відповідь №1.c)

Розумний вказівник std::weak_ptr слід використовувати, коли потрібно мати доступ до ресурсу, яким керує інший розумний вказівник std::shared_ptr, але тривалість життя цих двох розумних вказівників не повинні бути пов’язані між собою.

d) Розумний вказівник std::auto_ptr

Відповідь №1.d)

Розумний вказівник std::auto_ptr застарів, і його слід уникати.

Завдання №2

Поясніть, як посилання r-value беруть участь в реалізації семантики переміщення.

Відповідь №2

Оскільки значення r-values є тимчасовими, то ми знаємо, що вони будуть знищені відразу ж після їх використання. При передачі або поверненні r-value по значенню менш ефективним буде виконувати копіювання, а потім знищувати оригінал. Замість цього набагато ефективніше буде просто перемістити (передати) ресурси r-value в потрібний об’єкт.

Завдання №3

Що не так з наступними програмами? Оновіть їх відповідно до рекомендацій, розглянутих в цьому розділі.

a)

Відповідь №3.a)

ptr2 був створений з item-а, а не з ptr1. Це означає, що тепер у нас є два окремих розумних вказівники std::shared_ptr, кожен з яких намагається незалежно управляти Item-ом (вони не знають про існування один одного). Коли один з цих розумних вказівників вийде з області видимості, то інший залишиться “висячим” вказівником.

ptr2 повинен бути скопійований з ptr1, і для створення std::shared_ptr слід використовувати функцію std::make_shared():

b)

Відповідь №3.b)

Якщо конструктор класу Something викине виняток, то один з об’єктів класу Something, цілком ймовірно, не буде знищений належним чином.

Рішення полягає у використанні функції std::make_shared():

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (Немає Оцінок)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *