Advertisement
chevengur

СПРИНТ № 8 | Эффективные линейные контейнеры | Урок 10: Разработка контейнера SimpleVector 1

Jun 25th, 2024
694
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.55 KB | None | 0 0
  1. simple_vector.h
  2.  
  3. #pragma once
  4.  
  5. #include <cassert>
  6. #include <initializer_list>
  7. #include <vector>
  8. #include <exception>
  9. #include <algorithm>
  10. #include <iostream>
  11. #include "array_ptr.h"
  12.  
  13. template <typename Type>
  14. class SimpleVector {
  15. public:
  16.     using Iterator = Type*;
  17.     using ConstIterator = const Type*;
  18.  
  19.     SimpleVector() noexcept = default;
  20.  
  21.     // Создаёт вектор из size элементов, инициализированных значением по умолчанию
  22.     explicit SimpleVector(size_t size) : size_(size), capacity_(size), ptr_(size) {
  23.         std::fill(begin(), end(), 0);
  24.     }
  25.  
  26.     // Создаёт вектор из size элементов, инициализированных значением value
  27.     SimpleVector(size_t size, const Type& value) : size_(size), capacity_(size), ptr_(size) {
  28.         std::fill(begin(), end(), value);
  29.     }
  30.  
  31.     // Создаёт вектор из std::initializer_list
  32.     SimpleVector(std::initializer_list<Type> init) : size_(init.size()), capacity_(init.size()), ptr_(init.size())
  33.     {
  34.         size_t b = 0;
  35.         for (const auto& i : init)
  36.         {
  37.             ptr_[b] = i;
  38.             ++b;
  39.         }
  40.     }
  41.  
  42.     ~SimpleVector() {}
  43.  
  44.     // Возвращает количество элементов в массиве
  45.     size_t GetSize() const noexcept {
  46.         return size_;
  47.     }
  48.  
  49.     // Возвращает вместимость массива
  50.     size_t GetCapacity() const noexcept {
  51.         return capacity_;
  52.     }
  53.  
  54.     // Сообщает, пустой ли массив
  55.     bool IsEmpty() const noexcept {
  56.         return size_ == 0;
  57.     }
  58.  
  59.     // Возвращает ссылку на элемент с индексом index
  60.     Type& operator[](size_t index) noexcept {
  61.         return ptr_[index];
  62.     }
  63.  
  64.     // Возвращает константную ссылку на элемент с индексом index
  65.     const Type& operator[](size_t index) const noexcept {
  66.  
  67.         return ptr_[index];
  68.     }
  69.  
  70.     // Возвращает константную ссылку на элемент с индексом index
  71.     // Выбрасывает исключение std::out_of_range, если index >= size
  72.     Type& At(size_t index) {
  73.         if (index >= size_)
  74.             throw std::out_of_range("out of range");
  75.         return ptr_[index];
  76.     }
  77.  
  78.     // Возвращает константную ссылку на элемент с индексом index
  79.     // Выбрасывает исключение std::out_of_range, если index >= size
  80.     const Type& At(size_t index) const {
  81.         if (index > size_)
  82.             throw std::out_of_range("out of range");
  83.         return ptr_[index];
  84.     }
  85.  
  86.     // Обнуляет размер массива, не изменяя его вместимость
  87.     void Clear() noexcept {
  88.         size_ = 0;
  89.     }
  90.  
  91.     // Изменяет размер массива.
  92.     // При увеличении размера новые элементы получают значение по умолчанию для типа Type
  93.     void Resize(size_t new_size) {
  94.         if (new_size > capacity_) {
  95.             auto new_array = ArrayPtr<Type>(new_size);
  96.             for (size_t i = 0; i < size_; ++i) {
  97.                 new_array[i] = ptr_[i];
  98.             }
  99.             ptr_.swap(new_array);
  100.             capacity_ = new_size;
  101.         }
  102.         for (size_t i = size_; i < new_size; ++i) {
  103.             ptr_[i] = Type();
  104.         }
  105.         size_ = new_size;
  106.     }
  107.  
  108.     // Возвращает итератор на начало массива
  109.     // Для пустого массива может быть равен (или не равен) nullptr
  110.     Iterator begin() noexcept {
  111.         return ptr_.Get();
  112.         // Напишите тело самостоятельно
  113.     }
  114.  
  115.     // Возвращает итератор на элемент, следующий за последним
  116.     // Для пустого массива может быть равен (или не равен) nullptr
  117.     Iterator end() noexcept {
  118.         return ptr_.Get() + size_;
  119.     }
  120.  
  121.     // Возвращает константный итератор на начало массива
  122.     // Для пустого массива может быть равен (или не равен) nullptr
  123.     ConstIterator begin() const noexcept {
  124.         return ptr_.Get();
  125.     }
  126.  
  127.     // Возвращает итератор на элемент, следующий за последним
  128.     // Для пустого массива может быть равен (или не равен) nullptr
  129.     ConstIterator end() const noexcept {
  130.         return ptr_.Get() + size_;
  131.     }
  132.  
  133.     // Возвращает константный итератор на начало массива
  134.     // Для пустого массива может быть равен (или не равен) nullptr
  135.     ConstIterator cbegin() const noexcept {
  136.         return ptr_.Get();
  137.     }
  138.  
  139.     // Возвращает итератор на элемент, следующий за последним
  140.     // Для пустого массива может быть равен (или не равен) nullptr
  141.     ConstIterator cend() const noexcept {
  142.         return ptr_.Get() + size_;
  143.     }
  144. private:
  145.     size_t size_ = 0;
  146.     size_t capacity_ = 0;
  147.     ArrayPtr<Type> ptr_;
  148. };
  149.  
  150. =======================================================================================================================================
  151.  
  152. test.h
  153.  
  154. #pragma once
  155. #include <cassert>
  156. #include <stdexcept>
  157.  
  158. // У функции, объявленной со спецификатором inline, может быть несколько
  159. // идентичных определений в разных единицах трансляции.
  160. // Обычно inline помечают функции, чьё тело находится в заголовочном файле,
  161. // чтобы при подключении этого файла из разных единиц трансляции не возникало ошибок компоновки
  162. inline void Test1() {
  163.     //Инициализация конструктором по умолчанию
  164.     {
  165.         SimpleVector<int> v;
  166.         assert(v.GetSize() == 0u);
  167.         assert(v.IsEmpty());
  168.         assert(v.GetCapacity() == 0u);
  169.     }
  170.  
  171.     // Инициализация вектора указанного размера
  172.     {
  173.         SimpleVector<int> v(5);
  174.         assert(v.GetSize() == 5u);
  175.         assert(v.GetCapacity() == 5u);
  176.         assert(!v.IsEmpty());
  177.         for (size_t i = 0; i < v.GetSize(); ++i) {
  178.             assert(v[i] == 0);
  179.         }
  180.     }
  181.  
  182.     // Инициализация вектора, заполненного заданным значением
  183.     {
  184.         SimpleVector<int> v(3, 42);
  185.         assert(v.GetSize() == 3);
  186.         assert(v.GetCapacity() == 3);
  187.         for (size_t i = 0; i < v.GetSize(); ++i) {
  188.             assert(v[i] == 42);
  189.         }
  190.     }
  191.  
  192.     // Инициализация вектора при помощи initializer_list
  193.     {
  194.         SimpleVector<int> v{1, 2, 3};
  195.         assert(v.GetSize() == 3);
  196.         assert(v.GetCapacity() == 3);
  197.         assert(v[2] == 3);
  198.     }
  199.  
  200.     //Доступ к элементам при помощи At
  201.     {
  202.         SimpleVector<int> v(3);
  203.         assert(&v.At(2) == &v[2]);
  204.         try {
  205.             v.At(3);
  206.             assert(false);  // Ожидается выбрасывание исключения
  207.         } catch (const std::out_of_range&) {
  208.         } catch (...) {
  209.             assert(false);  // Не ожидается исключение, отличное от out_of_range
  210.         }
  211.     }
  212.  
  213.     // Очистка вектора
  214.     {
  215.         SimpleVector<int> v(10);
  216.         const size_t old_capacity = v.GetCapacity();
  217.         v.Clear();
  218.         assert(v.GetSize() == 0);
  219.         assert(v.GetCapacity() == old_capacity);
  220.     }
  221.  
  222.     // Изменение размера
  223.     {
  224.         SimpleVector<int> v(3);
  225.         v[2] = 17;
  226.         v.Resize(7);
  227.         assert(v.GetSize() == 7);
  228.         assert(v.GetCapacity() >= v.GetSize());
  229.         assert(v[2] == 17);
  230.         assert(v[3] == 0);
  231.     }
  232.     {
  233.         SimpleVector<int> v(3);
  234.         v[0] = 42;
  235.         v[1] = 55;
  236.         const size_t old_capacity = v.GetCapacity();
  237.         v.Resize(2);
  238.         assert(v.GetSize() == 2);
  239.         assert(v.GetCapacity() == old_capacity);
  240.         assert(v[0] == 42);
  241.         assert(v[1] == 55);
  242.     }
  243.     {
  244.         const size_t old_size = 3;
  245.         SimpleVector<int> v(3);
  246.         v.Resize(old_size + 5);
  247.         v[3] = 42;
  248.         v.Resize(old_size);
  249.         v.Resize(old_size + 2);
  250.         assert(v[3] == 0);
  251.     }
  252.  
  253.     // Итерирование по SimpleVector
  254.     {
  255.         // Пустой вектор
  256.         {
  257.             SimpleVector<int> v;
  258.             assert(v.begin() == nullptr);
  259.             assert(v.end() == nullptr);
  260.         }
  261.  
  262.         // Непустой вектор
  263.         {
  264.             SimpleVector<int> v(10, 42);
  265.             assert(v.begin());
  266.             assert(*v.begin() == 42);
  267.             assert(v.end() == v.begin() + v.GetSize());
  268.         }
  269.     }
  270. }
  271.  
  272. =======================================================================================================================================
  273.  
  274. #include <cassert>
  275. #include <cstdlib>
  276.  
  277. template <typename Type>
  278. class ArrayPtr {
  279. public:
  280.     ArrayPtr() = default;
  281.  
  282.     explicit ArrayPtr(size_t size) {
  283.         (size == 0) ? raw_ptr_ = nullptr : raw_ptr_ = new Type[size];
  284.     }
  285.  
  286.     explicit ArrayPtr(Type* raw_ptr) noexcept {
  287.         if (raw_ptr) raw_ptr_ = raw_ptr;
  288.     }
  289.  
  290.     ArrayPtr(const ArrayPtr&) = delete;
  291.  
  292.     ~ArrayPtr() {
  293.         delete[] raw_ptr_;
  294.     }
  295.  
  296.     ArrayPtr& operator=(const ArrayPtr&) = delete;
  297.  
  298.     [[nodiscard]] Type* Release() noexcept {
  299.         Type* currentarr = raw_ptr_;
  300.         raw_ptr_ = nullptr;
  301.         return currentarr;
  302.     }
  303.  
  304.     Type& operator[](size_t index) noexcept {
  305.         return raw_ptr_[index];
  306.     }
  307.  
  308.     const Type& operator[](size_t index) const noexcept {
  309.         return raw_ptr_[index];
  310.     }
  311.  
  312.     explicit operator bool() const {
  313.         return (raw_ptr_) ? true : false;
  314.     }
  315.  
  316.     Type* Get() const noexcept {
  317.         return raw_ptr_;
  318.  
  319.     }
  320.  
  321.     void swap(ArrayPtr& other) noexcept {
  322.         Type* temp = other.raw_ptr_;
  323.         other.raw_ptr_ = raw_ptr_;
  324.         raw_ptr_ = temp;
  325.     }
  326.  
  327. private:
  328.     Type* raw_ptr_ = nullptr;
  329. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement