Advertisement
kutuzzzov

Урок 5 Обработка исключений

Jul 18th, 2023
1,052
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.26 KB | None | 0 0
  1. #pragma once
  2. #include <cassert>
  3. #include <cstdlib>
  4. #include <new>
  5. #include <utility>
  6.  
  7. template <typename T>
  8. class Vector {
  9. public:
  10.     Vector() = default;
  11.  
  12.     explicit Vector(size_t size)
  13.         : data_(Allocate(size))
  14.         , capacity_(size)
  15.         , size_(size)  //
  16.     {
  17.         size_t counter = 0;
  18.         try {
  19.             for (; counter != size; ++counter) {
  20.                 new (data_ + counter) T();
  21.             }
  22.         }
  23.         catch (...) {
  24.             DestroyN(data_, counter);
  25.             Deallocate(data_);
  26.             throw;
  27.         }
  28.     }
  29.  
  30.     Vector(const Vector& other)
  31.         : data_(Allocate(other.size_))
  32.         , capacity_(other.size_)
  33.         , size_(other.size_)
  34.     {
  35.         size_t counter = 0;
  36.         try {
  37.             for (; counter != other.size_; ++counter) {
  38.                 CopyConstruct(data_ + counter, other.data_[counter]);
  39.             }
  40.         }
  41.         catch (...) {
  42.             DestroyN(data_, counter);
  43.             Deallocate(data_);
  44.             throw;
  45.         }
  46.     }
  47.  
  48.     ~Vector() {
  49.         DestroyN(data_, size_);
  50.         Deallocate(data_);
  51.     }
  52.  
  53.     size_t Size() const noexcept {
  54.         return size_;
  55.     }
  56.  
  57.     size_t Capacity() const noexcept {
  58.         return capacity_;
  59.     }
  60.  
  61.     void Reserve(size_t new_capacity) {
  62.         if (new_capacity <= capacity_) {
  63.             return;
  64.         }
  65.         size_t counter = 0;
  66.         T* new_data = Allocate(new_capacity);
  67.         try {
  68.             for (; counter != size_; ++counter) {
  69.                 CopyConstruct(new_data + counter, data_[counter]);
  70.             }
  71.             DestroyN(data_, size_);
  72.             Deallocate(data_);
  73.  
  74.             data_ = new_data;
  75.             capacity_ = new_capacity;
  76.         }
  77.         catch (...) {
  78.             DestroyN(new_data, counter);
  79.             Deallocate(new_data);
  80.             throw;
  81.         }
  82.     }
  83.  
  84.     const T& operator[](size_t index) const noexcept {
  85.         return const_cast<Vector&>(*this)[index];
  86.     }
  87.  
  88.     T& operator[](size_t index) noexcept {
  89.         assert(index < size_);
  90.         return data_[index];
  91.     }
  92.  
  93. private:
  94.     // Выделяет сырую память под n элементов и возвращает указатель на неё
  95.     static T* Allocate(size_t n) {
  96.         return n != 0 ? static_cast<T*>(operator new(n * sizeof(T))) : nullptr;
  97.     }
  98.  
  99.     // Освобождает сырую память, выделенную ранее по адресу buf при помощи Allocate
  100.     static void Deallocate(T* buf) noexcept {
  101.         operator delete(buf);
  102.     }
  103.  
  104.     // Вызывает деструкторы n объектов массива по адресу buf
  105.     static void DestroyN(T* buf, size_t n) noexcept {
  106.         for (size_t i = 0; i != n; ++i) {
  107.             Destroy(buf + i);
  108.         }
  109.     }
  110.  
  111.     // Создаёт копию объекта elem в сырой памяти по адресу buf
  112.     static void CopyConstruct(T* buf, const T& elem) {
  113.         new (buf) T(elem);
  114.     }
  115.  
  116.     // Вызывает деструктор объекта по адресу buf
  117.     static void Destroy(T* buf) noexcept {
  118.         buf->~T();
  119.     }
  120.  
  121.     T* data_ = nullptr;
  122.     size_t capacity_ = 0;
  123.     size_t size_ = 0;
  124. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement