Advertisement
chevengur

СПРИНТ № 7 | Модель памяти в C++ | Урок 8: Копирование объектов. Часть вторая 1/2

Apr 19th, 2024 (edited)
979
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.06 KB | None | 0 0
  1. #include <cassert>
  2.  
  3. // Умный указатель, удаляющий связанный объект при своём разрушении.
  4. // Параметр шаблона T задаёт тип объекта, на который ссылается указатель
  5. template <typename T>
  6. class ScopedPtr {
  7. public:
  8.     // Конструктор по умолчанию создаёт нулевой указатель,
  9.     // так как поле ptr_ имеет значение по умолчанию nullptr
  10.     ScopedPtr() = default;
  11.  
  12.     // Создаёт указатель, ссылающийся на переданный raw_ptr.
  13.     // raw_ptr ссылается либо на объект, созданный в куче при помощи new,
  14.     // либо является нулевым указателем
  15.     // Спецификатор noexcept обозначает, что метод не бросает исключений
  16.     explicit ScopedPtr(T* raw_ptr) noexcept {
  17.         if (raw_ptr != nullptr)
  18.         {
  19.             ptr_ = raw_ptr;
  20.         }
  21.     }
  22.  
  23.     // Удаляем у класса конструктор копирования
  24.     ScopedPtr(const ScopedPtr&) = delete;
  25.  
  26.     // Деструктор. Удаляет объект, на который ссылается умный указатель.
  27.     ~ScopedPtr() {
  28.         // Реализуйте тело деструктора самостоятельно
  29.         delete ptr_;
  30.     }
  31.  
  32.     // Возвращает указатель, хранящийся внутри ScopedPtr
  33.     T* GetRawPtr() const noexcept {
  34.  
  35.         return ptr_;
  36.         // Напишите код метода самостоятельно
  37.     }
  38.  
  39.     // Прекращает владение объектом, на который ссылается умный указатель.
  40.     // Возвращает прежнее значение "сырого" указателя и устанавливает поле ptr_ в null
  41.     T* Release() noexcept {
  42.         // Реализуйте самостоятельно
  43.         T* new_ptr = ptr_;
  44.         ptr_ = nullptr;
  45.         return new_ptr;
  46.        
  47.     }
  48.  
  49. private:
  50.     T* ptr_ = nullptr;
  51. };
  52.  
  53. // Этот main тестирует класс ScopedPtr
  54. int main() {
  55.     // Вспомогательный "шпион", позволяющий узнать о своём удалении
  56.     struct DeletionSpy {
  57.         explicit DeletionSpy(bool& is_deleted)
  58.             : is_deleted_(is_deleted) {
  59.         }
  60.         ~DeletionSpy() {
  61.             is_deleted_ = true;
  62.         }
  63.         bool& is_deleted_;
  64.     };
  65.  
  66.     // Проверяем автоматическое удаление
  67.     {
  68.         bool is_deleted = false;
  69.         {
  70.             // настраиваем "шпион", чтобы при своём удалении он выставил is_deleted в true
  71.             DeletionSpy* raw_ptr = new DeletionSpy(is_deleted);
  72.             ScopedPtr<DeletionSpy> p(raw_ptr);
  73.             assert(p.GetRawPtr() == raw_ptr);
  74.             assert(!is_deleted);
  75.             // При выходе из блока деструктор p должен удалить "шпиона"
  76.         }
  77.         // Если деструктор умного указателя работает правильно, шпион перед своей "смертью"
  78.         // должен выставить is_deleted в true
  79.         assert(is_deleted);
  80.     }
  81.  
  82.     // Проверяем работу метода Release
  83.     {
  84.         bool is_deleted = false;
  85.         DeletionSpy* raw_ptr = new DeletionSpy(is_deleted);
  86.         {
  87.             ScopedPtr<DeletionSpy> scoped_ptr(raw_ptr);
  88.             assert(scoped_ptr.Release() == raw_ptr);
  89.             assert(scoped_ptr.GetRawPtr() == nullptr);
  90.             // После Release умный указатель не ссылается на объект и не удаляет его при своём удалении
  91.         }
  92.         assert(!is_deleted);
  93.         delete raw_ptr;
  94.         assert(is_deleted);
  95.     }
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement