Advertisement
kutuzzzov

Урок 9 реализация методов..

Jul 19th, 2023
1,349
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.17 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.     void Resize(size_t new_size) {
  183.         if (new_size < size_) {
  184.             std::destroy_n(data_.GetAddress() + new_size, size_ - new_size);
  185.             size_ = new_size;
  186.         }
  187.         else {
  188.             Reserve(new_size);
  189.             std::uninitialized_value_construct_n(data_.GetAddress() + size_, new_size - size_);
  190.             size_ = new_size;
  191.         }
  192.     }
  193.  
  194.     void PushBack(const T& value) {
  195.         if (size_ == Capacity()) {
  196.             RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  197.             std::uninitialized_copy_n(&value, 1, new_data.GetAddress() + size_);
  198.             if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  199.                 std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  200.             }
  201.             else {
  202.                 std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  203.             }
  204.             std::destroy_n(data_.GetAddress(), size_);
  205.             data_.Swap(new_data);
  206.         }
  207.         else {
  208.             new (data_ + size_) T(value);
  209.         }
  210.         ++size_;
  211.     }
  212.  
  213.     void PushBack(T&& value) {
  214.         if (size_ == Capacity()) {
  215.             RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  216.             std::uninitialized_move_n(&value, 1, new_data.GetAddress() + size_);
  217.             if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  218.                 std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  219.             }
  220.             else {
  221.                 std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  222.             }
  223.             std::destroy_n(data_.GetAddress(), size_);
  224.             data_.Swap(new_data);
  225.         }
  226.         else {
  227.             new (data_ + size_) T(std::move(value));
  228.         }
  229.         ++size_;
  230.     }
  231.  
  232.     void PopBack() noexcept {
  233.         if (size_ > 0) {
  234.             std::destroy_at(data_.GetAddress() + size_ - 1);
  235.             --size_;
  236.         }
  237.     }
  238.  
  239. private:
  240.     RawMemory<T> data_;
  241.     size_t size_ = 0;
  242. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement