shushus

Спринт 14. Реализация методов Resize, PushBack и PopBack.

May 5th, 2023
489
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.96 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. vector.h
  3. -----------------------------------------------------------------------
  4. #pragma once
  5. #include <cassert>
  6. #include <memory>
  7. #include <algorithm>
  8. #include <cstdlib>
  9. #include <new>
  10. #include <utility>
  11.  
  12. template <typename T>
  13. class RawMemory {
  14. public:
  15.     RawMemory() = default;
  16.  
  17.     explicit RawMemory(size_t capacity) : buffer_(Allocate(capacity))
  18.                                         , capacity_(capacity) {}
  19.  
  20.     ~RawMemory() {Deallocate(buffer_);}
  21.    
  22.     RawMemory(const RawMemory&) = delete;
  23.     RawMemory& operator=(const RawMemory& rhs) = delete;
  24.    
  25.     RawMemory(RawMemory&& other) noexcept : buffer_(std::exchange(other.buffer_, nullptr))
  26.                                           , capacity_(std::exchange(other.capacity_, 0)) {}
  27.  
  28.     RawMemory& operator=(RawMemory&& rhs) noexcept {
  29.        
  30.         if (this != &rhs) {
  31.             buffer_ = std::move(rhs.buffer_);
  32.             capacity_ = std::move(rhs.capacity_);
  33.             rhs.buffer_ = nullptr;
  34.             rhs.capacity_ = 0;
  35.         }
  36.        
  37.         return *this;
  38.     }
  39.  
  40.     T* operator+(size_t offset) noexcept {assert(offset <= capacity_); return buffer_ + offset;}
  41.     const T* operator+(size_t offset) const noexcept {return const_cast<RawMemory&>(*this) + offset;}
  42.  
  43.     const T& operator[](size_t index) const noexcept {return const_cast<RawMemory&>(*this)[index];}
  44.     T& operator[](size_t index) noexcept {assert(index < capacity_); return buffer_[index];}
  45.  
  46.     void Swap(RawMemory& other) noexcept {std::swap(buffer_, other.buffer_); std::swap(capacity_, other.capacity_);}
  47.  
  48.     const T* GetAddress() const noexcept {return buffer_;}
  49.     T* GetAddress() noexcept {return buffer_;}
  50.     size_t Capacity() const {return capacity_;}
  51.  
  52. private:
  53.     T* buffer_ = nullptr;
  54.     size_t capacity_ = 0;
  55.    
  56.     static T* Allocate(size_t n) {return n != 0 ? static_cast<T*>(operator new(n * sizeof(T))) : nullptr;}
  57.     static void Deallocate(T* buf) noexcept {operator delete(buf);}
  58. };
  59.  
  60. template <typename T>
  61. class Vector {
  62. public:
  63.    
  64.     Vector() = default;
  65.  
  66.     explicit Vector(size_t size) : data_(size)
  67.                                  , size_(size) {std::uninitialized_value_construct_n(data_.GetAddress(), size);}
  68.    
  69.     Vector(const Vector& other) : data_(other.size_)
  70.                                 , size_(other.size_) {std::uninitialized_copy_n(other.data_.GetAddress(), size_, data_.GetAddress());}
  71.    
  72.     Vector(Vector&& other) noexcept : data_(std::move(other.data_))
  73.                                     , size_(std::exchange(other.size_, 0)) {}
  74.    
  75.     ~Vector() {std::destroy_n(data_.GetAddress(), size_);}
  76.    
  77.     size_t Size() const noexcept {return size_;}
  78.     size_t Capacity() const noexcept {return data_.Capacity();}
  79.     void Swap(Vector& other) noexcept {data_.Swap(other.data_), std::swap(size_, other.size_);}
  80.    
  81.     void Reserve(size_t new_capacity) {
  82.        
  83.         if (new_capacity <= data_.Capacity()) {
  84.             return;
  85.         }
  86.        
  87.         RawMemory<T> new_data(new_capacity);
  88.        
  89.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  90.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  91.         } else {
  92.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  93.         }
  94.        
  95.         std::destroy_n(data_.GetAddress(), size_);
  96.         data_.Swap(new_data);
  97.     }
  98.  
  99.     void Resize(size_t new_size) {
  100.        
  101.         if (new_size < size_) {
  102.             std::destroy_n(data_.GetAddress() + new_size, size_ - new_size);
  103.            
  104.         } else {
  105.            
  106.             if (new_size > data_.Capacity()) {
  107.                 const size_t new_capacity = std::max(data_.Capacity() * 2, new_size);
  108.                
  109.                 Reserve(new_capacity);
  110.             }
  111.            
  112.             std::uninitialized_value_construct_n(data_.GetAddress() + size_, new_size - size_);
  113.         }
  114.        
  115.         size_ = new_size;
  116.     }
  117.    
  118.     template <typename Type>
  119.     void PushBack(Type&& value);
  120.  
  121.     void PopBack() {
  122.         assert(size_);
  123.         std::destroy_at(data_.GetAddress() + size_ - 1);
  124.         --size_;
  125.     }
  126.    
  127.     Vector& operator=(const Vector& other) {
  128.        
  129.         if (this != &other) {
  130.            
  131.             if (other.size_ <= data_.Capacity()) {
  132.                
  133.                 if (size_ <= other.size_) {
  134.                    
  135.                     std::copy(other.data_.GetAddress(),
  136.                               other.data_.GetAddress() + size_,
  137.                               data_.GetAddress());
  138.                    
  139.                     std::uninitialized_copy_n(other.data_.GetAddress() + size_,
  140.                                               other.size_ - size_,
  141.                                               data_.GetAddress() + size_);
  142.                 } else {
  143.                    
  144.                     std::copy(other.data_.GetAddress(),
  145.                               other.data_.GetAddress() + other.size_,
  146.                               data_.GetAddress());
  147.                    
  148.                     std::destroy_n(data_.GetAddress() + other.size_,
  149.                                    size_ - other.size_);
  150.                 }
  151.                
  152.                 size_ = other.size_;
  153.                
  154.             } else {              
  155.                 Vector other_copy(other);
  156.                 Swap(other_copy);
  157.             }
  158.         }
  159.        
  160.         return *this;
  161.     }
  162.  
  163.     Vector& operator=(Vector&& other) noexcept {Swap(other); return *this;}
  164.    
  165.     const T& operator[](size_t index) const noexcept {return const_cast<Vector&>(*this)[index];}
  166.     T& operator[](size_t index) noexcept {assert(index < size_); return data_[index];}
  167.  
  168. private:
  169.     RawMemory<T> data_;
  170.     size_t size_ = 0;
  171. };
  172.  
  173. template <typename T>
  174. template <typename Type>
  175. void Vector<T>::PushBack(Type&& value) {
  176.  
  177.     if (data_.Capacity() <= size_) {
  178.    
  179.         RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  180.        
  181.         new (new_data.GetAddress() + size_) T(std::forward<Type>(value));
  182.        
  183.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  184.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  185.         } else {
  186.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  187.         }
  188.        
  189.         std::destroy_n(data_.GetAddress(), size_);
  190.         data_.Swap(new_data);
  191.        
  192.     } else {
  193.         new (data_.GetAddress() + size_) T(std::forward<Type>(value));
  194.     }
  195.    
  196.     size_++;
  197. }
  198. -----------------------------------------------------------------------
  199. main.cpp
  200. -----------------------------------------------------------------------
  201. #include "vector.h"
  202.  
  203. #include <stdexcept>
  204.  
  205. namespace {
  206.    
  207. inline const uint32_t DEFAULT_COOKIE = 0xdeadbeef;
  208.  
  209. struct TestObj {
  210.  
  211.     TestObj() = default;
  212.     TestObj(const TestObj& other) = default;
  213.     TestObj& operator=(const TestObj& other) = default;
  214.     TestObj(TestObj&& other) = default;
  215.     TestObj& operator=(TestObj&& other) = default;
  216.  
  217.     ~TestObj() {cookie = 0;}
  218.     [[nodiscard]] bool IsAlive() const noexcept {return cookie == DEFAULT_COOKIE;}
  219.     uint32_t cookie = DEFAULT_COOKIE;
  220. };
  221.  
  222. struct Obj {
  223.  
  224.     Obj() {
  225.  
  226.         if (default_construction_throw_countdown > 0) {
  227.  
  228.             if (--default_construction_throw_countdown == 0) {
  229.                 throw std::runtime_error("Oops");
  230.             }
  231.         }
  232.  
  233.         ++num_default_constructed;
  234.     }
  235.  
  236.     explicit Obj(int id) : id(id) {++num_constructed_with_id;}
  237.  
  238.     Obj(const Obj& other) : id(other.id) {
  239.  
  240.         if (other.throw_on_copy) {
  241.             throw std::runtime_error("Oops");
  242.         }
  243.  
  244.         ++num_copied;
  245.     }
  246.  
  247.     Obj(Obj&& other) noexcept : id(other.id) {++num_moved;}
  248.  
  249.     Obj& operator=(const Obj& other) = default;
  250.     Obj& operator=(Obj&& other) = default;
  251.  
  252.     ~Obj() {++num_destroyed; id = 0;}
  253.  
  254.     static int GetAliveObjectCount() {
  255.  
  256.         return num_default_constructed
  257.             + num_copied
  258.             + num_moved
  259.             + num_constructed_with_id
  260.             - num_destroyed;
  261.     }
  262.  
  263.     static void ResetCounters() {
  264.         default_construction_throw_countdown = 0;
  265.         num_default_constructed = 0;
  266.         num_copied = 0;
  267.         num_moved = 0;
  268.         num_destroyed = 0;
  269.         num_constructed_with_id = 0;
  270.     }
  271.  
  272.     bool throw_on_copy = false;
  273.     int id = 0;
  274.  
  275.     static inline int default_construction_throw_countdown = 0;
  276.     static inline int num_default_constructed = 0;
  277.     static inline int num_constructed_with_id = 0;
  278.     static inline int num_copied = 0;
  279.     static inline int num_moved = 0;
  280.     static inline int num_destroyed = 0;
  281. };
  282.  
  283. }//end namespace
  284.  
  285. void Test1() {
  286.    
  287.     Obj::ResetCounters();
  288.    
  289.     const size_t SIZE = 100500;
  290.     const size_t INDEX = 10;
  291.     const int MAGIC = 42;
  292.    
  293.     {
  294.         Vector<int> v;
  295.         assert(v.Capacity() == 0);
  296.         assert(v.Size() == 0);
  297.  
  298.         v.Reserve(SIZE);
  299.         assert(v.Capacity() == SIZE);
  300.         assert(v.Size() == 0);
  301.     }
  302.    
  303.     {
  304.         Vector<int> v(SIZE);
  305.        
  306.         const auto& cv(v);
  307.         assert(v.Capacity() == SIZE);
  308.         assert(v.Size() == SIZE);
  309.         assert(v[0] == 0);
  310.         assert(&v[0] == &cv[0]);
  311.         v[INDEX] = MAGIC;
  312.         assert(v[INDEX] == MAGIC);
  313.         assert(&v[100] - &v[0] == 100);
  314.  
  315.         v.Reserve(SIZE * 2);
  316.         assert(v.Size() == SIZE);
  317.         assert(v.Capacity() == SIZE * 2);
  318.         assert(v[INDEX] == MAGIC);
  319.     }
  320.    
  321.     {
  322.         Vector<int> v(SIZE);
  323.        
  324.         v[INDEX] = MAGIC;
  325.         const auto v_copy(v);
  326.         assert(&v[INDEX] != &v_copy[INDEX]);
  327.         assert(v[INDEX] == v_copy[INDEX]);
  328.     }
  329.    
  330.     {
  331.         Vector<Obj> v;
  332.        
  333.         v.Reserve(SIZE);
  334.         assert(Obj::GetAliveObjectCount() == 0);
  335.     }
  336.    
  337.     {
  338.         Vector<Obj> v(SIZE);
  339.        
  340.         assert(Obj::GetAliveObjectCount() == SIZE);
  341.        
  342.         const int old_copy_count = Obj::num_copied;
  343.         const int old_move_count = Obj::num_moved;
  344.         v.Reserve(SIZE * 2);
  345.         assert(Obj::GetAliveObjectCount() == SIZE);
  346.         assert(Obj::num_copied == old_copy_count);
  347.         assert(Obj::num_moved == old_move_count + static_cast<int>(SIZE));
  348.     }
  349.    
  350.     assert(Obj::GetAliveObjectCount() == 0);
  351. }
  352.  
  353. void Test2() {
  354.     const size_t SIZE = 100;
  355.    
  356.     Obj::ResetCounters();
  357.    
  358.     {
  359.         Obj::default_construction_throw_countdown = SIZE / 2;
  360.         try {
  361.             Vector<Obj> v(SIZE);
  362.             assert(false && "Exception is expected");
  363.            
  364.         } catch (const std::runtime_error&) {
  365.            
  366.         } catch (...) {
  367.             assert(false && "Unexpected exception");
  368.         }
  369.        
  370.         assert(Obj::num_default_constructed == SIZE / 2 - 1);
  371.         assert(Obj::GetAliveObjectCount() == 0);
  372.     }
  373.    
  374.     Obj::ResetCounters();
  375.    
  376.     {
  377.         Vector<Obj> v(SIZE);
  378.        
  379.         try {
  380.             v[SIZE / 2].throw_on_copy = true;
  381.             Vector<Obj> v_copy(v);
  382.             assert(false && "Exception is expected");
  383.            
  384.         } catch (const std::runtime_error&) {
  385.             assert(Obj::num_copied == SIZE / 2);
  386.            
  387.         } catch (...) {
  388.             assert(false && "Unexpected exception");
  389.         }
  390.        
  391.         assert(Obj::GetAliveObjectCount() == SIZE);
  392.     }
  393.    
  394.     Obj::ResetCounters();
  395.    
  396.     {
  397.         Vector<Obj> v(SIZE);
  398.        
  399.         try {
  400.             v[SIZE - 1].throw_on_copy = true;
  401.             v.Reserve(SIZE * 2);
  402.            
  403.         } catch (...) {
  404.             assert(false && "Unexpected exception");
  405.         }
  406.        
  407.         assert(v.Capacity() == SIZE * 2);
  408.         assert(v.Size() == SIZE);
  409.         assert(Obj::GetAliveObjectCount() == SIZE);
  410.     }
  411. }
  412.  
  413. void Test3() {
  414.     const size_t MEDIUM_SIZE = 100;
  415.     const size_t LARGE_SIZE = 250;
  416.     const int ID = 42;
  417.    
  418.     {
  419.         Obj::ResetCounters();
  420.        
  421.         Vector<int> v(MEDIUM_SIZE);
  422.        
  423.         {
  424.             auto v_copy(std::move(v));
  425.  
  426.             assert(v_copy.Size() == MEDIUM_SIZE);
  427.             assert(v_copy.Capacity() == MEDIUM_SIZE);
  428.         }
  429.        
  430.         assert(Obj::GetAliveObjectCount() == 0);
  431.     }
  432.    
  433.     {
  434.         Obj::ResetCounters();
  435.        
  436.         {
  437.             Vector<Obj> v(MEDIUM_SIZE);
  438.            
  439.             v[MEDIUM_SIZE / 2].id = ID;
  440.             assert(Obj::num_default_constructed == MEDIUM_SIZE);
  441.             Vector<Obj> moved_from_v(std::move(v));
  442.             assert(moved_from_v.Size() == MEDIUM_SIZE);
  443.             assert(moved_from_v[MEDIUM_SIZE / 2].id == ID);
  444.         }
  445.        
  446.         assert(Obj::GetAliveObjectCount() == 0);
  447.  
  448.         assert(Obj::num_moved == 0);
  449.         assert(Obj::num_copied == 0);
  450.         assert(Obj::num_default_constructed == MEDIUM_SIZE);
  451.     }
  452.    
  453.     {
  454.         Obj::ResetCounters();
  455.        
  456.         Vector<Obj> v_medium(MEDIUM_SIZE);
  457.        
  458.         v_medium[MEDIUM_SIZE / 2].id = ID;
  459.         Vector<Obj> v_large(LARGE_SIZE);
  460.         v_large = v_medium;
  461.         assert(v_large.Size() == MEDIUM_SIZE);
  462.         assert(v_large.Capacity() == LARGE_SIZE);
  463.         assert(v_large[MEDIUM_SIZE / 2].id == ID);
  464.         assert(Obj::GetAliveObjectCount() == MEDIUM_SIZE + MEDIUM_SIZE);
  465.     }
  466.    
  467.     {
  468.         Obj::ResetCounters();
  469.        
  470.         Vector<Obj> v(MEDIUM_SIZE);
  471.        
  472.         {
  473.             Vector<Obj> v_large(LARGE_SIZE);
  474.            
  475.             v_large[LARGE_SIZE - 1].id = ID;
  476.             v = v_large;
  477.             assert(v.Size() == LARGE_SIZE);
  478.             assert(v_large.Capacity() == LARGE_SIZE);
  479.             assert(v_large[LARGE_SIZE - 1].id == ID);
  480.             assert(Obj::GetAliveObjectCount() == LARGE_SIZE + LARGE_SIZE);
  481.         }
  482.        
  483.         assert(Obj::GetAliveObjectCount() == LARGE_SIZE);
  484.     }
  485.    
  486.     assert(Obj::GetAliveObjectCount() == 0);
  487.    
  488.     {
  489.         Obj::ResetCounters();
  490.        
  491.         Vector<Obj> v(MEDIUM_SIZE);
  492.        
  493.         v[MEDIUM_SIZE - 1].id = ID;
  494.         Vector<Obj> v_small(MEDIUM_SIZE / 2);
  495.         v_small.Reserve(MEDIUM_SIZE + 1);
  496.         const size_t num_copies = Obj::num_copied;
  497.        
  498.         v_small = v;
  499.         assert(v_small.Size() == v.Size());
  500.         assert(v_small.Capacity() == MEDIUM_SIZE + 1);
  501.        
  502.         v_small[MEDIUM_SIZE - 1].id = ID;
  503.         assert(Obj::num_copied - num_copies == MEDIUM_SIZE - (MEDIUM_SIZE / 2));
  504.     }
  505. }
  506.  
  507. void Test4() {
  508.     const size_t ID = 42;
  509.     const size_t SIZE = 100'500;
  510.    
  511.    {
  512.        Obj::ResetCounters();
  513.        
  514.        Vector<Obj> v;
  515.        
  516.        v.Resize(SIZE);
  517.        assert(v.Size() == SIZE);
  518.        assert(v.Capacity() == SIZE);
  519.        assert(Obj::num_default_constructed == SIZE);
  520.    }
  521.    
  522.    assert(Obj::GetAliveObjectCount() == 0);
  523.  
  524.    {
  525.        const size_t NEW_SIZE = 10'000;
  526.        
  527.         Obj::ResetCounters();
  528.        
  529.         Vector<Obj> v(SIZE);
  530.        
  531.         v.Resize(NEW_SIZE);
  532.         assert(v.Size() == NEW_SIZE);
  533.         assert(v.Capacity() == SIZE);
  534.         assert(Obj::num_destroyed == SIZE - NEW_SIZE);
  535.     }
  536.    
  537.     assert(Obj::GetAliveObjectCount() == 0);
  538.    
  539.     {
  540.         Obj::ResetCounters();
  541.        
  542.         Vector<Obj> v(SIZE);
  543.        
  544.         Obj o{ID};
  545.         v.PushBack(o);
  546.         assert(v.Size() == SIZE + 1);
  547.         assert(v.Capacity() == SIZE * 2);
  548.         assert(v[SIZE].id == ID);
  549.         assert(Obj::num_default_constructed == SIZE);
  550.         assert(Obj::num_copied == 1);
  551.         assert(Obj::num_constructed_with_id == 1);
  552.         assert(Obj::num_moved == SIZE);
  553.     }
  554.    
  555.     assert(Obj::GetAliveObjectCount() == 0);
  556.    
  557.     {
  558.         Obj::ResetCounters();
  559.        
  560.         Vector<Obj> v(SIZE);
  561.        
  562.         v.PushBack(Obj{ID});
  563.         assert(v.Size() == SIZE + 1);
  564.         assert(v.Capacity() == SIZE * 2);
  565.         assert(v[SIZE].id == ID);
  566.         assert(Obj::num_default_constructed == SIZE);
  567.         assert(Obj::num_copied == 0);
  568.         assert(Obj::num_constructed_with_id == 1);
  569.         assert(Obj::num_moved == SIZE + 1);
  570.     }
  571.    
  572.     {
  573.         Obj::ResetCounters();
  574.        
  575.         Vector<Obj> v;
  576.        
  577.         v.PushBack(Obj{ID});
  578.         v.PopBack();
  579.         assert(v.Size() == 0);
  580.         assert(v.Capacity() == 1);
  581.         assert(Obj::GetAliveObjectCount() == 0);
  582.     }
  583.  
  584.     {
  585.         Vector<TestObj> v(1);
  586.        
  587.         assert(v.Size() == v.Capacity());
  588.         v.PushBack(v[0]);
  589.         assert(v[0].IsAlive());
  590.         assert(v[1].IsAlive());
  591.     }
  592.     {
  593.         Vector<TestObj> v(1);
  594.        
  595.         assert(v.Size() == v.Capacity());
  596.         v.PushBack(std::move(v[0]));
  597.         assert(v[0].IsAlive());
  598.         assert(v[1].IsAlive());
  599.     }
  600. }
  601.  
  602. int main() {
  603.     Test1();
  604.     Test2();
  605.     Test3();
  606.     Test4();
  607. }
Advertisement
Add Comment
Please, Sign In to add comment