Глава №15. Итоговый тест

  Юрий  | 

  |

  Обновл. 8 Апр 2021  | 

 14802

 ǀ   2 

Еще одна глава позади. Последний итоговый тест. Пора закрепить пройденный материал.

Теория

Класс умного указателя — это класс, предназначенный для управления динамически выделенной памятью и для её удаления, когда объект умного указателя выходит из области видимости.

Семантика копирования позволяет копировать классы с помощью конструктора копирования и оператора присваивания копированием.

Семантика перемещения позволяет классу передать владение ресурсами/объектом с помощью конструктора перемещения и оператора присваивания перемещением другому объекту (без выполнения копирования).

Умный указатель 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 (100 оценок, среднее: 4,88 из 5)
Загрузка...

Комментариев: 2

  1. Константин:

    Ответ на 3а:

    и на 3б:

  2. osoznanie:

    Не хватает, конечно, тестов практических)
    От теории немного голова болит)
    Спасибо за перевод!

Добавить комментарий для Константин Отменить ответ

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