Advertisement
kutuzzzov

Урок 4 наивная реализация вектора

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