Advertisement
chevengur

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

Jun 27th, 2024
532
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.63 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(const SimpleVector& other): size_(other.size_), capacity_(other.capacity_), ptr_(other.size_){
  43.         std::copy(other.begin(), other.end(), begin());
  44.     }
  45.  
  46.     SimpleVector& operator=(const SimpleVector& rhs) {
  47.         SimpleVector copy{ rhs };
  48.         swap(copy);
  49.         return *this;
  50.     }
  51.  
  52.  
  53.     ~SimpleVector() {}
  54.  
  55.     // Возвращает количество элементов в массиве
  56.     size_t GetSize() const noexcept {
  57.         return size_;
  58.     }
  59.  
  60.     // Возвращает вместимость массива
  61.     size_t GetCapacity() const noexcept {
  62.         return capacity_;
  63.     }
  64.  
  65.     // Сообщает, пустой ли массив
  66.     bool IsEmpty() const noexcept {
  67.         return size_ == 0;
  68.     }
  69.  
  70.     // Возвращает ссылку на элемент с индексом index
  71.     Type& operator[](size_t index) noexcept {
  72.         return ptr_[index];
  73.     }
  74.  
  75.     // Возвращает константную ссылку на элемент с индексом index
  76.     const Type& operator[](size_t index) const noexcept {
  77.  
  78.         return ptr_[index];
  79.     }
  80.  
  81.     // Возвращает константную ссылку на элемент с индексом index
  82.     // Выбрасывает исключение std::out_of_range, если index >= size
  83.     Type& At(size_t index) {
  84.         if (index >= size_)
  85.             throw std::out_of_range("out of range");
  86.         return ptr_[index];
  87.     }
  88.  
  89.     // Возвращает константную ссылку на элемент с индексом index
  90.     // Выбрасывает исключение std::out_of_range, если index >= size
  91.     const Type& At(size_t index) const {
  92.         if (index > size_)
  93.             throw std::out_of_range("out of range");
  94.         return ptr_[index];
  95.     }
  96.  
  97.     // Обнуляет размер массива, не изменяя его вместимость
  98.     void Clear() noexcept {
  99.         size_ = 0;
  100.     }
  101.  
  102.     // Изменяет размер массива.
  103.     // При увеличении размера новые элементы получают значение по умолчанию для типа Type
  104.     void Resize(size_t new_size) {
  105.         if (new_size > capacity_) {
  106.             auto new_array = ArrayPtr<Type>(new_size);
  107.             for (size_t i = 0; i < size_; ++i) {
  108.                 new_array[i] = ptr_[i];
  109.             }
  110.             ptr_.swap(new_array);
  111.             capacity_ = new_size;
  112.         }
  113.         for (size_t i = size_; i < new_size; ++i) {
  114.             ptr_[i] = Type();
  115.         }
  116.         size_ = new_size;
  117.     }
  118.  
  119.     // Возвращает итератор на начало массива
  120.     // Для пустого массива может быть равен (или не равен) nullptr
  121.     Iterator begin() noexcept {
  122.         return ptr_.Get();
  123.         // Напишите тело самостоятельно
  124.     }
  125.  
  126.     // Возвращает итератор на элемент, следующий за последним
  127.     // Для пустого массива может быть равен (или не равен) nullptr
  128.     Iterator end() noexcept {
  129.         return ptr_.Get() + size_;
  130.     }
  131.  
  132.     // Возвращает константный итератор на начало массива
  133.     // Для пустого массива может быть равен (или не равен) nullptr
  134.     ConstIterator begin() const noexcept {
  135.         return ptr_.Get();
  136.     }
  137.  
  138.     // Возвращает итератор на элемент, следующий за последним
  139.     // Для пустого массива может быть равен (или не равен) nullptr
  140.     ConstIterator end() const noexcept {
  141.         return ptr_.Get() + size_;
  142.     }
  143.  
  144.     // Возвращает константный итератор на начало массива
  145.     // Для пустого массива может быть равен (или не равен) nullptr
  146.     ConstIterator cbegin() const noexcept {
  147.         return ptr_.Get();
  148.     }
  149.  
  150.     // Возвращает итератор на элемент, следующий за последним
  151.     // Для пустого массива может быть равен (или не равен) nullptr
  152.     ConstIterator cend() const noexcept {
  153.         return ptr_.Get() + size_;
  154.     }
  155.  
  156.     // Добавляет элемент в конец вектора
  157.     // При нехватке места увеличивает вдвое вместимость вектора
  158.     void PushBack(const Type& item) {
  159.        if(size_ == capacity_)
  160.        {
  161.             auto new_capacity = (capacity_ == 0) ? 1 : capacity_ * 2;
  162.             auto new_vector = ArrayPtr<Type>(new_capacity);
  163.             for (size_t i = 0; i < size_; ++i)
  164.             {
  165.                 new_vector[i] = ptr_[i];
  166.             }
  167.             ptr_.swap(new_vector);
  168.             capacity_ = new_capacity;
  169.        }
  170.        ptr_[size_] = item;
  171.        ++size_;
  172.     }
  173.  
  174.     // Вставляет значение value в позицию pos.
  175.     // Возвращает итератор на вставленное значение
  176.     // Если перед вставкой значения вектор был заполнен полностью,
  177.     // вместимость вектора должна увеличиться вдвое, а для вектора вместимостью 0 стать равной 1
  178.     Iterator Insert(ConstIterator pos, const Type& value) {
  179.         size_t index = pos - begin();
  180.         if(index > capacity_)
  181.         {
  182.             std::out_of_range("exit of out_of_range");
  183.         }
  184.         if(size_ == capacity_)
  185.         {
  186.             auto new_capacity = (capacity_ == 0) ? 1 : capacity_ * 2;
  187.             auto new_vector = ArrayPtr<Type>(new_capacity);
  188.             std::copy(begin(), begin()+index, new_vector.Get());
  189.             new_vector[index] = value;
  190.             std::copy(begin()+index, end(), new_vector.Get()+index+1);
  191.             ptr_.swap(new_vector);
  192.             capacity_ = new_capacity;
  193.         }
  194.         else{
  195.             std::copy_backward(begin()+index, end(), end()+1);
  196.             ptr_[index] = value;
  197.         }
  198.         ++size_;
  199.         return Iterator(ptr_.Get() + index);
  200.     }
  201.  
  202.     // "Удаляет" последний элемент вектора. Вектор не должен быть пустым
  203.     void PopBack() noexcept {
  204.         if(size_) --size_;
  205.     }
  206.  
  207.     // Удаляет элемент вектора в указанной позиции
  208.     Iterator Erase(ConstIterator pos) {
  209.         auto index = pos-begin();
  210.        
  211.         if(size_)
  212.         {
  213.             auto new_vector = ArrayPtr<Type>(capacity_);
  214.             std::copy(begin(), begin()+index, new_vector.Get());
  215.            
  216.             std::copy(begin() + index+1, end(), new_vector.Get()+index);
  217.             --size_;
  218.             ptr_.swap(new_vector);
  219.         }
  220.         return Iterator(begin() + index);
  221.     }
  222.  
  223.     // Обменивает значение с другим вектором
  224.     void swap(SimpleVector& other) noexcept {
  225.         std::swap(size_, other.size_);
  226.         std::swap(capacity_, other.capacity_);
  227.         ptr_.swap(other.ptr_);
  228.     }
  229. private:
  230.     size_t size_ = 0;
  231.     size_t capacity_ = 0;
  232.     ArrayPtr<Type> ptr_;
  233. };
  234.  
  235. template <typename Type>
  236. inline bool operator==(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  237.     return std::equal(lhs.begin(), lhs.end(), rhs.begin());
  238. }
  239.  
  240. template <typename Type>
  241. inline bool operator!=(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  242.     return !(rhs==lhs);
  243. }
  244.  
  245. template <typename Type>
  246. inline bool operator<(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  247.     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  248.    
  249. }
  250.  
  251. template <typename Type>
  252. inline bool operator<=(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  253.     // Заглушка. Напишите тело самостоятельно
  254.     return (lhs<rhs) || (lhs==rhs);
  255. }
  256.  
  257. template <typename Type>
  258. inline bool operator>(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  259.     return std::lexicographical_compare(rhs.begin(), rhs.end(), lhs.begin(), lhs.end());
  260. }
  261.  
  262. template <typename Type>
  263. inline bool operator>=(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  264.     // Заглушка. Напишите тело самостоятельно
  265.     return (lhs>rhs) || (lhs==rhs);
  266. }
  267.  
  268. =======================================================================================================================================
  269.  
  270. array_ptr.h
  271.  
  272. #include <cassert>
  273. #include <cstdlib>
  274.  
  275. template <typename Type>
  276. class ArrayPtr {
  277. public:
  278.     ArrayPtr() = default;
  279.  
  280.     explicit ArrayPtr(size_t size) {
  281.         (size == 0) ? raw_ptr_ = nullptr : raw_ptr_ = new Type[size];
  282.     }
  283.  
  284.     explicit ArrayPtr(Type* raw_ptr) noexcept {
  285.         if (raw_ptr) raw_ptr_ = raw_ptr;
  286.     }
  287.  
  288.     ArrayPtr(const ArrayPtr&) = delete;
  289.  
  290.     ~ArrayPtr() {
  291.         delete[] raw_ptr_;
  292.     }
  293.  
  294.     ArrayPtr& operator=(const ArrayPtr&) = delete;
  295.  
  296.     [[nodiscard]] Type* Release() noexcept {
  297.         Type* currentarr = raw_ptr_;
  298.         raw_ptr_ = nullptr;
  299.         return currentarr;
  300.     }
  301.  
  302.     Type& operator[](size_t index) noexcept {
  303.         return raw_ptr_[index];
  304.     }
  305.  
  306.     const Type& operator[](size_t index) const noexcept {
  307.         return raw_ptr_[index];
  308.     }
  309.  
  310.     explicit operator bool() const {
  311.         return (raw_ptr_) ? true : false;
  312.     }
  313.  
  314.     Type* Get() const noexcept {
  315.         return raw_ptr_;
  316.     }
  317.  
  318.     void swap(ArrayPtr& other) noexcept {
  319.         Type* temp = other.raw_ptr_;
  320.         other.raw_ptr_ = raw_ptr_;
  321.         raw_ptr_ = temp;
  322.     }
  323.  
  324. private:
  325.     Type* raw_ptr_ = nullptr;
  326. };
  327.  
  328. =======================================================================================================================================
  329.  
  330. tests.h
  331.  
  332. #pragma once
  333. #include <cassert>
  334. #include <stdexcept>
  335. #include "simple_vector.h"
  336.  
  337. inline void Test1() {
  338.    // Инициализация конструктором по умолчанию
  339.    {
  340.        SimpleVector<int> v;
  341.        assert(v.GetSize() == 0u);
  342.        assert(v.IsEmpty());
  343.        assert(v.GetCapacity() == 0u);
  344.    }
  345.  
  346.    // Инициализация вектора указанного размера
  347.    {
  348.        SimpleVector<int> v(5);
  349.        assert(v.GetSize() == 5u);
  350.        assert(v.GetCapacity() == 5u);
  351.        assert(!v.IsEmpty());
  352.        for (size_t i = 0; i < v.GetSize(); ++i) {
  353.            assert(v[i] == 0);
  354.        }
  355.    }
  356.  
  357.    // Инициализация вектора, заполненного заданным значением
  358.    {
  359.        SimpleVector<int> v(3, 42);
  360.        assert(v.GetSize() == 3);
  361.        assert(v.GetCapacity() == 3);
  362.        for (size_t i = 0; i < v.GetSize(); ++i) {
  363.            assert(v[i] == 42);
  364.        }
  365.    }
  366.  
  367.    // Инициализация вектора при помощи initializer_list
  368.    {
  369.        SimpleVector<int> v{ 1, 2, 3 };
  370.        assert(v.GetSize() == 3);
  371.        assert(v.GetCapacity() == 3);
  372.        assert(v[2] == 3);
  373.    }
  374.  
  375.    // Доступ к элементам при помощи At
  376.    {
  377.        SimpleVector<int> v(3);
  378.        assert(&v.At(2) == &v[2]);
  379.        try {
  380.            v.At(3);
  381.            assert(false);  // Ожидается выбрасывание исключения
  382.        }
  383.        catch (const std::out_of_range&) {
  384.        }
  385.        catch (...) {
  386.            assert(false);  // Не ожидается исключение, отличное от out_of_range
  387.        }
  388.    }
  389.  
  390.    // Очистка вектора
  391.    {
  392.        SimpleVector<int> v(10);
  393.        const size_t old_capacity = v.GetCapacity();
  394.        v.Clear();
  395.        assert(v.GetSize() == 0);
  396.        assert(v.GetCapacity() == old_capacity);
  397.    }
  398.  
  399.    // Изменение размера
  400.    {
  401.        SimpleVector<int> v(3);
  402.        v[2] = 17;
  403.        v.Resize(7);
  404.        assert(v.GetSize() == 7);
  405.        assert(v.GetCapacity() >= v.GetSize());
  406.        assert(v[2] == 17);
  407.        assert(v[3] == 0);
  408.    }
  409.    {
  410.        SimpleVector<int> v(3);
  411.        v[0] = 42;
  412.        v[1] = 55;
  413.        const size_t old_capacity = v.GetCapacity();
  414.        v.Resize(2);
  415.        assert(v.GetSize() == 2);
  416.        assert(v.GetCapacity() == old_capacity);
  417.        assert(v[0] == 42);
  418.        assert(v[1] == 55);
  419.    }
  420.    {
  421.        const size_t old_size = 3;
  422.        SimpleVector<int> v(3);
  423.        v.Resize(old_size + 5);
  424.        v[3] = 42;
  425.        v.Resize(old_size);
  426.        v.Resize(old_size + 2);
  427.        assert(v[3] == 0);
  428.    }
  429.  
  430.    // Итерирование по SimpleVector
  431.    {
  432.        // Пустой вектор
  433.        {
  434.            SimpleVector<int> v;
  435.            assert(v.begin() == nullptr);
  436.            assert(v.end() == nullptr);
  437.        }
  438.  
  439.        // Непустой вектор
  440.        {
  441.            SimpleVector<int> v(10, 42);
  442.            assert(v.begin());
  443.            assert(*v.begin() == 42);
  444.            assert(v.end() == v.begin() + v.GetSize());
  445.        }
  446.    }
  447. }
  448.  
  449. inline void Test2() {
  450.    // PushBack
  451.    {
  452.        SimpleVector<int> v(1);
  453.        v.PushBack(42);
  454.        assert(v.GetSize() == 2);
  455.        assert(v.GetCapacity() >= v.GetSize());
  456.        assert(v[0] == 0);
  457.        assert(v[1] == 42);
  458.    }
  459.  
  460.    // Если хватает места, PushBack не увеличивает Capacity
  461.    {
  462.        SimpleVector<int> v(2);
  463.        v.Resize(1);
  464.        const size_t old_capacity = v.GetCapacity();
  465.        v.PushBack(123);
  466.        assert(v.GetSize() == 2);
  467.        assert(v.GetCapacity() == old_capacity);
  468.    }
  469.  
  470.    // PopBack
  471.    {
  472.        SimpleVector<int> v{ 0, 1, 2, 3 };
  473.        const size_t old_capacity = v.GetCapacity();
  474.        const auto old_begin = v.begin();
  475.        v.PopBack();
  476.        assert(v.GetCapacity() == old_capacity);
  477.        assert(v.begin() == old_begin);
  478.        assert((v == SimpleVector<int>{0, 1, 2}));
  479.    }
  480.  
  481.    // Конструктор копирования
  482.    {
  483.        SimpleVector<int> numbers{ 1, 2 };
  484.        auto numbers_copy(numbers);
  485.        assert(&numbers_copy[0] != &numbers[0]);
  486.        assert(numbers_copy.GetSize() == numbers.GetSize());
  487.        for (size_t i = 0; i < numbers.GetSize(); ++i) {
  488.            assert(numbers_copy[i] == numbers[i]);
  489.            assert(&numbers_copy[i] != &numbers[i]);
  490.        }
  491.    }
  492.  
  493.    // Сравнение
  494.    {
  495.        assert((SimpleVector{ 1, 2, 3 } == SimpleVector{ 1, 2, 3 }));
  496.        assert((SimpleVector{ 1, 2, 3 } != SimpleVector{ 1, 2, 2 }));
  497.  
  498.        assert((SimpleVector{ 1, 2, 3 } < SimpleVector{ 1, 2, 3, 1 }));
  499.        assert((SimpleVector{ 1, 2, 3 } > SimpleVector{ 1, 2, 2, 1 }));
  500.  
  501.        assert((SimpleVector{ 1, 2, 3 } >= SimpleVector{ 1, 2, 3 }));
  502.        assert((SimpleVector{ 1, 2, 4 } >= SimpleVector{ 1, 2, 3 }));
  503.        assert((SimpleVector{ 1, 2, 3 } <= SimpleVector{ 1, 2, 3 }));
  504.        assert((SimpleVector{ 1, 2, 3 } <= SimpleVector{ 1, 2, 4 }));
  505.     }
  506.  
  507.    // Обмен значений векторов
  508.    {
  509.        SimpleVector<int> v1{ 42, 666 };
  510.        SimpleVector<int> v2;
  511.        v2.PushBack(0);
  512.        v2.PushBack(1);
  513.        v2.PushBack(2);
  514.        const int* const begin1 = &v1[0];
  515.        const int* const begin2 = &v2[0];
  516.  
  517.        const size_t capacity1 = v1.GetCapacity();
  518.        const size_t capacity2 = v2.GetCapacity();
  519.  
  520.        const size_t size1 = v1.GetSize();
  521.        const size_t size2 = v2.GetSize();
  522.  
  523.        static_assert(noexcept(v1.swap(v2)));
  524.        v1.swap(v2);
  525.        assert(&v2[0] == begin1);
  526.        assert(&v1[0] == begin2);
  527.        assert(v1.GetSize() == size2);
  528.        assert(v2.GetSize() == size1);
  529.        assert(v1.GetCapacity() == capacity2);
  530.        assert(v2.GetCapacity() == capacity1);
  531.    }
  532.  
  533.    // Присваивание
  534.    {
  535.        SimpleVector<int> src_vector{ 1, 2, 3, 4 };
  536.        SimpleVector<int> dst_vector{ 1, 2, 3, 4, 5, 6 };
  537.        dst_vector = src_vector;
  538.        assert(dst_vector == src_vector);
  539.    }
  540.  
  541.    // Вставка элементов
  542.    {
  543.        SimpleVector<int> v{ 1, 2, 3, 4 };
  544.        v.Insert(v.begin() + 2, 42);
  545.        assert((v == SimpleVector<int>{1, 2, 42, 3, 4}));
  546.    }
  547.  
  548.  
  549.    // Удаление элементов
  550.    {
  551.        SimpleVector<int> v{ 1, 2, 3, 4 };
  552.        v.Erase(v.cbegin() + 2);
  553.        assert((v == SimpleVector<int>{1, 2, 4}));
  554.    }
  555.  
  556. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement