shushus

Спринт 14. Наивная реализация базового функционала класса Vector.

May 5th, 2023
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.55 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. vector.h
  3. -----------------------------------------------------------------------
  4. #pragma once
  5. #include <cassert>
  6. #include <cstdlib>
  7. #include <new>
  8. #include <utility>
  9.  
  10. template <typename T>
  11. class Vector {
  12. public:
  13.    
  14.     Vector() = default;
  15.  
  16.     explicit Vector(size_t size) : data_(Allocate(size))
  17.                                  , capacity_(size)
  18.                                  , size_(size) {
  19.        
  20.         for (size_t i = 0; i != size; ++i) {
  21.             new (data_ + i) T();
  22.         }
  23.     }
  24.    
  25.     ~Vector() {DestroyN(data_, size_); Deallocate(data_);}
  26.    
  27.     Vector(const Vector& other) : data_(Allocate(other.size_))
  28.                                 , capacity_(other.size_)
  29.                                 , size_(other.size_) {
  30.        
  31.         for (size_t i = 0; i != other.size_; ++i) {
  32.             CopyConstruct(data_ + i, other.data_[i]);
  33.         }
  34.     }
  35.    
  36.     size_t Size() const noexcept {return size_;}
  37.     size_t Capacity() const noexcept {return capacity_;}
  38.    
  39.     void Reserve(size_t new_capacity) {
  40.        
  41.         if (new_capacity <= capacity_) {
  42.             return;
  43.         }
  44.        
  45.         T* new_data = Allocate(new_capacity);
  46.        
  47.         for (size_t i = 0; i != size_; ++i) {
  48.             CopyConstruct(new_data + i, data_[i]);
  49.         }
  50.        
  51.         DestroyN(data_, size_);
  52.         Deallocate(data_);
  53.  
  54.         data_ = new_data;
  55.         capacity_ = new_capacity;
  56.     }
  57.    
  58.     const T& operator[](size_t index) const noexcept {return const_cast<Vector&>(*this)[index];}
  59.     T& operator[](size_t index) noexcept {assert(index < size_); return data_[index];}
  60.  
  61. private:
  62.     T* data_ = nullptr;
  63.     size_t capacity_ = 0;
  64.     size_t size_ = 0;
  65.  
  66.     static T* Allocate(size_t n) {return n != 0 ? static_cast<T*>(operator new(n * sizeof(T))) : nullptr;}
  67.     static void Deallocate(T* buf) noexcept {operator delete(buf);}
  68.  
  69.     static void CopyConstruct(T* buf, const T& elem) {new (buf) T(elem);}
  70.     static void Destroy(T* buf) noexcept {buf->~T();}
  71.    
  72.     static void DestroyN(T* buf, size_t n) noexcept {
  73.        
  74.         for (size_t i = 0; i != n; ++i) {
  75.             Destroy(buf + i);
  76.         }
  77.     }
  78. };
  79. -----------------------------------------------------------------------
  80. main.cpp
  81. -----------------------------------------------------------------------
  82. #include "vector.h"
  83.  
  84. namespace {
  85.  
  86. struct Obj {
  87.    
  88.     Obj() {++num_default_constructed;}
  89.     Obj(const Obj& /*other*/) {++num_copied;}
  90.     Obj(Obj&& /*other*/) noexcept {++num_moved;}
  91.  
  92.     Obj& operator=(const Obj& other) = default;
  93.     Obj& operator=(Obj&& other) = default;
  94.  
  95.     ~Obj() {++num_destroyed;}
  96.  
  97.     static int GetAliveObjectCount() {return num_default_constructed + num_copied + num_moved - num_destroyed;}
  98.  
  99.     static void ResetCounters() {
  100.         num_default_constructed = 0;
  101.         num_copied = 0;
  102.         num_moved = 0;
  103.         num_destroyed = 0;
  104.     }
  105.  
  106.     static inline int num_default_constructed = 0;
  107.     static inline int num_copied = 0;
  108.     static inline int num_moved = 0;
  109.     static inline int num_destroyed = 0;
  110. };
  111.  
  112. }//end namespace
  113.  
  114. void Test1() {
  115.     Obj::ResetCounters();
  116.    
  117.     const size_t SIZE = 100500;
  118.     const size_t INDEX = 10;
  119.     const int MAGIC = 42;
  120.    
  121.     {
  122.         Vector<int> v;
  123.         assert(v.Capacity() == 0);
  124.         assert(v.Size() == 0);
  125.  
  126.         v.Reserve(SIZE);
  127.         assert(v.Capacity() == SIZE);
  128.         assert(v.Size() == 0);
  129.     }
  130.    
  131.     {
  132.         Vector<int> v(SIZE);
  133.         const auto& cv(v);
  134.         assert(v.Capacity() == SIZE);
  135.         assert(v.Size() == SIZE);
  136.         assert(v[0] == 0);
  137.         assert(&v[0] == &cv[0]);
  138.         v[INDEX] = MAGIC;
  139.         assert(v[INDEX] == MAGIC);
  140.         assert(&v[100] - &v[0] == 100);
  141.  
  142.         v.Reserve(SIZE * 2);
  143.         assert(v.Size() == SIZE);
  144.         assert(v.Capacity() == SIZE * 2);
  145.         assert(v[INDEX] == MAGIC);
  146.     }
  147.    
  148.     {
  149.         Vector<int> v(SIZE);
  150.         v[INDEX] = MAGIC;
  151.         const auto v_copy(v);
  152.         assert(&v[INDEX] != &v_copy[INDEX]);
  153.         assert(v[INDEX] == v_copy[INDEX]);
  154.     }
  155.    
  156.     {
  157.         Vector<Obj> v;
  158.         v.Reserve(SIZE);
  159.         assert(Obj::GetAliveObjectCount() == 0);
  160.     }
  161.    
  162.     {
  163.         Vector<Obj> v(SIZE);
  164.         assert(Obj::GetAliveObjectCount() == SIZE);
  165.         v.Reserve(SIZE * 2);
  166.         assert(Obj::GetAliveObjectCount() == SIZE);
  167.     }
  168.    
  169.     assert(Obj::GetAliveObjectCount() == 0);
  170. }
  171.  
  172. int main() {
  173.     Test1();
  174. }
Advertisement
Add Comment
Please, Sign In to add comment