c++定义一个成员为String的Vector 发表于 2016-11-29 自定义一个简化版的vector 123456789101112131415161718192021222324252627282930313233343536373839404142434445#ifndef STR_VEC#define STR_VEC#include<string>#include<memory>#include<iostream>#include<initializer_list>using std::string;class StrVec{public: StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){} StrVec(const StrVec&); StrVec(std::initializer_list<string>); StrVec& operator=(const StrVec&); StrVec(StrVec&&) noexcept; StrVec& operator=(StrVec&&) noexcept; ~StrVec(); void push_back(const string &); size_t size() const{return first_free-elements;} size_t capacity() const{return cap-elements;} string* begin() const{return elements;} string* end() const{return first_free;} string& at(size_t pos){return *(elements+pos);} const string& at(size_t pos) const{return *(elements+pos);} void resize(size_t count); void resize(size_t count, const string&); void reserve(size_t new_cap);private: static std::allocator<string> alloc; void chk_n_alloc(); std::pair<string*, string*> alloc_n_copy(const string*, const string*); void alloc_n_move(size_t new_cap); void range_initialize(const string*, const string*); void free(); //销毁元素并释放内存 void reallocate(); //获取更多内存并拷贝已有元素 string *elements; //指向数组首元素的指针 string *first_free; //指向数组第一个空闲元素的指针 string *cap; //指向数组尾后位置的指针};std::allocator<string> StrVec::alloc;#endif 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130#include "StrVec.hpp"#include<iostream>void StrVec::chk_n_alloc(){ std::cout<<"the size:"<<size()<<" the capacity:"<<capacity()<<std::endl; if (size() == capacity()) { reallocate(); std::cout<<"reallocate"<<std::endl; }}void StrVec::push_back(const string &s){ chk_n_alloc(); alloc.construct(first_free++, s);}std::pair<string *, string *> StrVec::alloc_n_copy(const string *b, const string *e){ auto data = alloc.allocate(e-b); return {data, uninitialized_copy(b,e,data)};}void StrVec::free(){ if(elements) { for(auto p = first_free; p != elements; ) alloc.destroy(--p); } //for_each(elements, first_free,[this](string &rhs){alloc.destroy(&rhs);}); alloc.deallocate(elements,cap-elements);}StrVec::StrVec(const StrVec &s){ range_initialize(s.begin(), s.end());}StrVec::StrVec(std::initializer_list<string>il){ range_initialize(il.begin(), il.end()); //il.begin()返回il中指向第一个元素的指针,il.end()返回il中指向最后一个元素最后元素的指针}void StrVec::range_initialize(const string* be, const string *en){ auto new_data = alloc_n_copy(be, en); elements = new_data.first; first_free = cap = new_data.first;}StrVec::~StrVec(){free();}StrVec& StrVec::operator=(const StrVec& rhs){ if(this != &rhs) { auto new_data = alloc_n_copy(rhs.begin(), rhs.end()); free(); elements = new_data.first; first_free = cap = new_data.first; return *this; }}StrVec::StrVec(StrVec && s)noexcept: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{ 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;}void StrVec::alloc_n_move(size_t new_cap){ auto new_data = alloc.allocate(new_cap); auto dest = new_data; auto elem = elements; for(; elem != first_free;) alloc.construct(dest++, std::move(*elem++)); free(); elements = new_data; first_free = dest; cap = new_data + new_cap;}void StrVec::reallocate(){ auto new_capacity = size() ? size()*2 : 1; alloc_n_move(new_capacity); std::cout<<"after reallocate,size: "<<size()<<", capacity:"<<capacity()<<std::endl;}void StrVec::reserve(size_t new_cap){ if(capacity() < new_cap) alloc_n_move(new_cap);}void StrVec::resize(size_t count){ resize(count,string());}void StrVec::resize(size_t count, const string &s){ if(count > size()) { if(count > capacity()) reserve(count*2); for(size_t i = size(); i != count; i++) alloc.construct(first_free++,s); } else if(count < size()) { while(first_free != elements+count) { alloc.destroy(--first_free); } }}