Advertisement
kutuzzzov

Урок 7 функция *

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