13.5 StrVec的实现

StrVec.h:

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

class StrVec
{
public:
   StrVec();
   StrVec(const StrVec &);
   StrVec &operator=(const StrVec &);

   StrVec(StrVec &&) noexcept;
   StrVec &operator=(StrVec &&) noexcept;

   ~StrVec();

   void push_back(const std::string &s);
   size_t size() const;
   size_t capacity() const;
   std::string *begin() const;
   std::string *end() const;
   void reserve(size_t n);
   void resize(size_t n, const std::string &s = std::string());
   void push_back(std::string &&s);

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

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

StrVec.cpp:

#include "stdafx.h"
#include <iostream>
#include "StrVec.h"

std::allocator<std::string> StrVec::alloc = std::allocator<std::string>();

StrVec::StrVec()
   : elements(nullptr), first_free(nullptr), cap(nullptr) {
   std::cout << "Default constructor" << std::endl;
}

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

StrVec &StrVec::operator=(const StrVec &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;
}

StrVec::StrVec(StrVec &&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;
}

StrVec &StrVec::operator=(StrVec &&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;
}

StrVec::~StrVec() {
   free();
}

void StrVec::push_back(std::string &&s) {
   check_volume();
   alloc.construct(first_free++, std::move(s));
}

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

void StrVec::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 = newPos;
   cap = first + newSize;
}

size_t StrVec::size() const {
   return first_free - elements;
}

size_t StrVec::capacity() const {
   return cap - elements;
}

void StrVec::push_back(const std::string &s) {
   check_volume();
   alloc.construct(first_free++, s);
}

std::string *StrVec::begin() const {
   return elements;
}

std::string *StrVec::end() const {
   return first_free;
}

void StrVec::check_volume() {
   if (size() == capacity()) reallocate();
}

void StrVec::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);
   }
}

void StrVec::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;
   }
}

void StrVec::resize(size_t n, const std::string &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:

using namespace std;

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

   StrVec c(std::move(b));
   a = std::move(c);

   return 0;
}

程序执行时出现failed:

C:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0 Line: 100
Expression: "(_Ptr_user &(_BIG_ALLOCATION_ALIGNMENT -1)) == 0" && 0

stackoverflow问题链接:
https://stackoverflow.com/questions/58341713/get-error-about-debug-assertion-failed-expression-ptr-user-big-allocatio

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值