Advertisement
kutuzzzov

Урок 8 оператор присваивания и..

Jul 19th, 2023
1,472
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.58 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(const RawMemory&) = delete;
  19.     RawMemory& operator=(const RawMemory& rhs) = delete;
  20.  
  21.     RawMemory(RawMemory&& other) noexcept {
  22.         buffer_ = std::move(other.GetAddress());
  23.         capacity_ = std::move(other.Capacity());
  24.     }
  25.  
  26.     RawMemory& operator=(RawMemory&& rhs) noexcept {
  27.         buffer_ = std::move(rhs.GetAddress());
  28.         capacity_ = std::move(rhs.Capacity());
  29.         //rhs.~RawMemory();
  30.         return *this;
  31.     }
  32.  
  33.     ~RawMemory() {
  34.         Deallocate(buffer_);
  35.     }
  36.  
  37.     T* operator+(size_t offset) noexcept {
  38.         // Разрешается получать адрес ячейки памяти, следующей за последним элементом массива
  39.         assert(offset <= capacity_);
  40.         return buffer_ + offset;
  41.     }
  42.  
  43.     const T* operator+(size_t offset) const noexcept {
  44.         return const_cast<RawMemory&>(*this) + offset;
  45.     }
  46.  
  47.     const T& operator[](size_t index) const noexcept {
  48.         return const_cast<RawMemory&>(*this)[index];
  49.     }
  50.  
  51.     T& operator[](size_t index) noexcept {
  52.         assert(index < capacity_);
  53.         return buffer_[index];
  54.     }
  55.  
  56.     void Swap(RawMemory& other) noexcept {
  57.         std::swap(buffer_, other.buffer_);
  58.         std::swap(capacity_, other.capacity_);
  59.     }
  60.  
  61.     const T* GetAddress() const noexcept {
  62.         return buffer_;
  63.     }
  64.  
  65.     T* GetAddress() noexcept {
  66.         return buffer_;
  67.     }
  68.  
  69.     size_t Capacity() const {
  70.         return capacity_;
  71.     }
  72.  
  73. private:
  74.     // Выделяет сырую память под n элементов и возвращает указатель на неё
  75.     static T* Allocate(size_t n) {
  76.         return n != 0 ? static_cast<T*>(operator new(n * sizeof(T))) : nullptr;
  77.     }
  78.  
  79.     // Освобождает сырую память, выделенную ранее по адресу buf при помощи Allocate
  80.     static void Deallocate(T* buf) noexcept {
  81.         operator delete(buf);
  82.     }
  83.  
  84.     T* buffer_ = nullptr;
  85.     size_t capacity_ = 0;
  86. };
  87.  
  88. template <typename T>
  89. class Vector {
  90. public:
  91.     Vector() = default;
  92.  
  93.     explicit Vector(size_t size)
  94.         : data_(size)
  95.         , size_(size)
  96.     {
  97.         std::uninitialized_value_construct_n(data_.GetAddress(), size);
  98.     }
  99.  
  100.     Vector(const Vector& other)
  101.         : data_(other.size_)
  102.         , size_(other.size_)
  103.     {
  104.         std::uninitialized_copy_n(other.data_.GetAddress(), size_, data_.GetAddress());
  105.     }
  106.    
  107.     Vector(Vector&& other) noexcept {
  108.         Swap(other);
  109.     }
  110.  
  111.     Vector& operator=(const Vector& rhs) {
  112.         if (this != &rhs) {
  113.             if (data_.Capacity() < rhs.size_) {
  114.                 Vector rhs_copy(rhs);
  115.                 Swap(rhs_copy);
  116.             }
  117.             else {
  118.                 if (rhs.size_ < size_) {
  119.                     std::copy(rhs.data_.GetAddress(), rhs.data_.GetAddress() + rhs.size_, data_.GetAddress());
  120.                     std::destroy_n(data_.GetAddress() + rhs.size_, size_ - rhs.size_);
  121.                 }
  122.                 else {
  123.                     std::copy(rhs.data_.GetAddress(), rhs.data_.GetAddress() + size_, data_.GetAddress());
  124.                     std::uninitialized_copy_n(rhs.data_.GetAddress() + size_, rhs.size_ - size_, data_.GetAddress() + size_);
  125.                 }
  126.                 size_ = rhs.size_;
  127.  
  128.             }
  129.         }
  130.         return *this;
  131.     }
  132.  
  133.     Vector& operator=(Vector&& rhs) noexcept {
  134.         if (this != &rhs) {
  135.             Swap(rhs);
  136.         }
  137.         return *this;
  138.     }
  139.  
  140.     void Swap(Vector& other) noexcept {
  141.         data_.Swap(other.data_);
  142.         std::swap(size_, other.size_);
  143.     }
  144.  
  145.     ~Vector() {
  146.         std::destroy_n(data_.GetAddress(), size_);
  147.     }
  148.  
  149.     size_t Size() const noexcept {
  150.         return size_;
  151.     }
  152.  
  153.     size_t Capacity() const noexcept {
  154.         return data_.Capacity();
  155.     }
  156.  
  157.     void Reserve(size_t new_capacity) {
  158.         if (new_capacity <= data_.Capacity()) {
  159.             return;
  160.         }
  161.         RawMemory<T> new_data(new_capacity);
  162.         // constexpr оператор if будет вычислен во время компиляции
  163.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  164.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  165.         }
  166.         else {
  167.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  168.         }
  169.         std::destroy_n(data_.GetAddress(), size_);
  170.         data_.Swap(new_data);
  171.     }
  172.  
  173.     const T& operator[](size_t index) const noexcept {
  174.         return const_cast<Vector&>(*this)[index];
  175.     }
  176.  
  177.     T& operator[](size_t index) noexcept {
  178.         assert(index < size_);
  179.         return data_[index];
  180.     }
  181.  
  182. private:
  183.     // Вызывает деструкторы n объектов массива по адресу buf
  184.     static void DestroyN(T* buf, size_t n) noexcept {
  185.         for (size_t i = 0; i != n; ++i) {
  186.             Destroy(buf + i);
  187.         }
  188.     }
  189.  
  190.     // Создаёт копию объекта elem в сырой памяти по адресу buf
  191.     static void CopyConstruct(T* buf, const T& elem) {
  192.         new (buf) T(elem);
  193.     }
  194.  
  195.     RawMemory<T> data_;
  196.     size_t size_ = 0;
  197. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement