16.16 Vec template class

Vec.h

#pragma once
#include <string>
#include <memory>

template <typename T>
class Vec
{
public:
   Vec();
   Vec(const Vec<T> &);
   Vec &operator=(const Vec<T> &);

   Vec(Vec<T> &&) noexcept;
   Vec &operator=(Vec<T> &&) noexcept;

   ~Vec();

   void push_back(const T &s);
   size_t size() const;
   size_t capacity() const;
   T *begin() const;
   T *end() const;
   void reserve(size_t n);
   void resize(size_t n, const T &s);
   void push_back(T &&s);

private:
   void check_volume();
   void reallocate();
   void free();
   std::pair<T *, T *>
      alloc_n_copy(const T *, const T *);

   T *elements;
   T *first_free;
   T *cap;
   static std::allocator<T> alloc;
};

template <typename T>
std::allocator<T> Vec<T>::alloc = std::allocator<T>();

template <typename T>
Vec<T>::Vec()
   : elements(nullptr), first_free(nullptr), cap(nullptr) {
   std::cout << "Default constructor" << std::endl;
}

template <typename T>
Vec<T>::Vec(const Vec &s) {
   std::cout << "Copy constructor" << std::endl;
   auto newBegin = alloc_n_copy(s.begin(), s.end());
   elements = newBegin.first;
   cap = first_free = newBegin.second;
}

template <typename T>
Vec<T> &Vec<T>::operator=(const Vec &rhs) {
   std::cout << "Assign operator" << std::endl;
   auto newBegin = alloc_n_copy(rhs.begin(), rhs.end());
   free();
   elements = newBegin.first;
   cap = first_free = newBegin.second;
   return *this;
}

template <typename T>
Vec<T>::Vec(Vec<T> &&s) noexcept {
   std::cout << "Move constructor" << std::endl;
   elements = s.elements;
   first_free = s.first_free;
   cap = s.cap;
   s.elements = s.first_free = s.cap = nullptr;
}

template <typename T>
Vec<T> &Vec<T>::operator=(Vec<T> &&rhs) noexcept {
   std::cout << "Move operator" << std::endl;
   if (this != &rhs) {
      free();
      elements = rhs.elements;
      first_free = rhs.first_free;
      cap = rhs.cap;
      rhs.elements = rhs.first_free = rhs.cap = nullptr;
   }
   return *this;
}

template <typename T>
Vec<T>::~Vec() {
   free();
}

template <typename T>
void Vec<T>::push_back(T &&s) {
   check_volume();
   alloc.construct(first_free++, std::move(s));
}

template <typename T>
std::pair<T *, T *>
Vec<T>::alloc_n_copy(const T *b, const T *e) {
   auto newMem = alloc.allocate(e - b);
   return{ newMem, std::uninitialized_copy(b, e, newMem) };
}

template <typename T>
void Vec<T>::reallocate() {
   size_t newSize = size() ? 2 * size() : 1;
   auto first = alloc.allocate(newSize);
   auto last = uninitialized_copy(make_move_iterator(begin()),
   								  make_move_iterator(end()),
   								  first);
   free();
   elements = first;
   first_free = last;
   cap = first + newSize;
}

template <typename T>
size_t Vec<T>::size() const {
   return first_free - elements;
}

template <typename T>
size_t Vec<T>::capacity() const {
   return cap - elements;
}

template <typename T>
void Vec<T>::push_back(const T &s) {
   check_volume();
   alloc.construct(first_free++, s);
}

template <typename T>
T *Vec<T>::begin() const {
   return elements;
}

template <typename T>
T *Vec<T>::end() const {
   return first_free;
}

template <typename T>
void Vec<T>::check_volume() {
   if (size() == capacity()) reallocate();
}

template <typename T>
void Vec<T>::free() {
   if (elements) {
      for (auto p = first_free; p != elements;) {
         alloc.destroy(--p); // should be destroy(--p); p point to the position after last elements, destroy a uninitialize pointer will lead to undefined behavior
      }
      alloc.deallocate(elements, cap - elements);
   }
}

template <typename T>
void Vec<T>::reserve(size_t n) {
   if (n > size()) {
      std::string *newBegin = alloc.allocate(n);
      std::string *new_first_free = std::uninitialized_copy(begin(), end(), newBegin);
      free();
      first_free = new_first_free;
      elements = newBegin;
      cap = newBegin + n;
   }
}

template <typename T>
void Vec<T>::resize(size_t n, const T &s) {
   std::string *newBegin = alloc.allocate(n);
   std::string *new_first_free = nullptr;
   if (n > size()) {
      auto p = std::uninitialized_copy(begin(), end(), newBegin);
      for (size_t i = 0; i < n - size(); ++i) {
         alloc.construct(p++, s);
      }
      new_first_free = p;
   }
   else {
      new_first_free = std::uninitialized_copy(begin(), begin() + n, newBegin);
   }
   first_free = new_first_free;
   elements = newBegin;
   cap = newBegin + n;
}

main.cpp

#include <iostream>
#include <string>
#include "Vec.h"

using namespace std;

int main()
{
   Vec<string> a;
   a.push_back("abc");
   Vec<string> b;
   cout << b.size() << endl;
   b = a;

   Vec<string> c(std::move(b));
   a = std::move(c);

   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值