Advertisement
kutuzzzov

Урок 9-1 копирование объектов ч. 3

Dec 9th, 2022
1,482
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.08 KB | None | 1 0
  1. #include <algorithm>
  2. #include <cassert>
  3. #include <vector>
  4. #include <stdexcept>
  5. #include <exception>
  6. #include <iostream>
  7.  
  8. using namespace std;
  9.  
  10. template <typename T>
  11. class PtrVector {
  12. public:
  13.     PtrVector() = default;
  14.  
  15.     // Создаёт вектор указателей на копии объектов из other
  16.     PtrVector(const PtrVector& other) {
  17.         // Реализуйте копирующий конструктор самостоятельно
  18.         items_.reserve(other.GetItems().size());
  19.        
  20.         for (auto item : other.GetItems()) {
  21.             if (item != nullptr) {
  22.                 T* item_copy = new T(*item);
  23.                 items_.push_back(item_copy);
  24.             } else {
  25.                 items_.push_back(nullptr);
  26.             }
  27.         }
  28.     }
  29.  
  30.     // Деструктор удаляет объекты в куче, на которые ссылаются указатели,
  31.     // в векторе items_
  32.     ~PtrVector() {
  33.         // Реализуйте тело деструктора самостоятельно
  34.         for (auto item : items_) {
  35.             delete item;
  36.         }
  37.     }
  38.  
  39.     // Возвращает ссылку на вектор указателей
  40.     vector<T*>& GetItems() noexcept {
  41.         // Реализуйте метод самостоятельно
  42.         return items_;
  43.     }
  44.  
  45.     // Возвращает константную ссылку на вектор указателей
  46.     vector<T*> const& GetItems() const noexcept {
  47.         // Реализуйте метод самостоятельно
  48.         return items_;
  49.     }
  50.  
  51. private:
  52.     vector<T*> items_;
  53. };
  54.  
  55. // Эта функция main тестирует шаблон класса PtrVector
  56. int main() {
  57.     // Вспомогательный "шпион", позволяющий узнать о своём удалении
  58.     struct DeletionSpy {
  59.         explicit DeletionSpy(bool& is_deleted)
  60.             : is_deleted_(is_deleted) {
  61.         }
  62.         ~DeletionSpy() {
  63.             is_deleted_ = true;
  64.         }
  65.         bool& is_deleted_;
  66.     };
  67.  
  68.     // Проверяем удаление элементов
  69.     {
  70.         bool spy1_is_deleted = false;
  71.         DeletionSpy* ptr1 = new DeletionSpy(spy1_is_deleted);
  72.         {
  73.             PtrVector<DeletionSpy> ptr_vector;
  74.             ptr_vector.GetItems().push_back(ptr1);
  75.             assert(!spy1_is_deleted);
  76.  
  77.             // Константная ссылка на ptr_vector
  78.             const auto& const_ptr_vector_ref(ptr_vector);
  79.             // И константная, и неконстантная версия GetItems
  80.             // должны вернуть ссылку на один и тот же вектор
  81.             assert(&const_ptr_vector_ref.GetItems() == &ptr_vector.GetItems());
  82.         }
  83.         // При разрушении ptr_vector должен удалить все объекты, на которые
  84.         // ссылаются находящиеся внутри него указателели
  85.         assert(spy1_is_deleted);
  86.     }
  87.  
  88.     // Вспомогательный «шпион», позволяющий узнать о своём копировании
  89.     struct CopyingSpy {
  90.         explicit CopyingSpy(int& copy_count)
  91.             : copy_count_(copy_count) {
  92.         }
  93.         CopyingSpy(const CopyingSpy& rhs)
  94.             : copy_count_(rhs.copy_count_)  //
  95.         {
  96.             ++copy_count_;
  97.         }
  98.         int& copy_count_;
  99.     };
  100.  
  101.     // Проверяем копирование элементов при копировании массива указателей
  102.     {
  103.         // 10 элементов
  104.         vector<int> copy_counters(10);
  105.  
  106.         PtrVector<CopyingSpy> ptr_vector;
  107.         // Подготавливаем оригинальный массив указателей
  108.         for (auto& counter : copy_counters) {
  109.             ptr_vector.GetItems().push_back(new CopyingSpy(counter));
  110.         }
  111.         // Последний элемент содержит нулевой указатель
  112.         ptr_vector.GetItems().push_back(nullptr);
  113.  
  114.         auto ptr_vector_copy(ptr_vector);
  115.         // Количество элементов в копии равно количеству элементов оригинального вектора
  116.         assert(ptr_vector_copy.GetItems().size() == ptr_vector.GetItems().size());
  117.  
  118.         // копия должна хранить указатели на новые объекты
  119.         assert(ptr_vector_copy.GetItems() != ptr_vector.GetItems());
  120.         // Последний элемент исходного массива и его копии - нулевой указатель
  121.         assert(ptr_vector_copy.GetItems().back() == nullptr);
  122.         // Проверяем, что элементы были скопированы (копирующие шпионы увеличивают счётчики копий).
  123.         assert(all_of(copy_counters.begin(), copy_counters.end(), [](int counter) {
  124.             return counter == 1;
  125.         }));
  126.     }
  127. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement