13.39 编写自己的StrVec,包括自己版本的reserve、capacity和resize。
13.40 为StrVec添加一个构造函数,它接受一个initializer_list<string>参数
StrVec.h
#ifndef STRVEC_H #define STRVEC_H #include<iostream> #include<string> #include<utility> #include<memory> using namespace std; class StrVec { public: StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){} StrVec(const StrVec&); StrVec& operator=(const StrVec&); ~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;} void reserve(size_t n); void resize(size_t n,string s=string()); StrVec(initializer_list<string> il) { auto newcapacity=il.size(); auto newdata=alloc.allocate(newcapacity); auto dest=newdata; auto elem=il.begin(); while(elem!=il.end()) alloc.construct(dest++,*elem); elements=newdata; first_free=cap=dest; } private: static allocator<string> alloc; string *elements; string *first_free; string *cap; void chk_n_alloc() { if(size()==capacity()) reallocate(); } pair<string*,string*> alloc_n_copy(const string*,const string*); void free(); void reallocate(); }; #endif // STRVEC_H
StrVec.cpp
#include"StrVec.h" allocator<string> StrVec::alloc; StrVec::StrVec(const StrVec &s) { auto newdata=alloc_n_copy(s.begin(),s.end()); elements=newdata.first; first_free=newdata.second; cap=newdata.second; } StrVec& StrVec::operator=(const StrVec &s) { auto data=alloc_n_copy(s.begin(),s.end()); free(); elements=data.first; first_free=cap=data.second; return *this; } StrVec::~StrVec() { free(); } void StrVec::push_back(const string &s) { chk_n_alloc(); alloc.construct(first_free++,s); } 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_each(&first_free,&elements,[](string *p) { alloc.destroy(p);}); lambda式子 for(auto p=first_free;p!=elements;) alloc.destroy(--p); alloc.deallocate(elements,cap-elements); } } void StrVec::reallocate() { auto newcapacity=size()?2*size():1; auto newdata=alloc.allocate(newcapacity); auto dest=newdata; auto elem=elements; for(size_t i=0;i!=size();++i) alloc.construct(dest++,std::move(*elem++)); elements=newdata; first_free=dest; cap=elements+newcapacity; } void StrVec::reserve(size_t n) { if(capacity()<n) reallocate(); } void StrVec::resize(size_t n,string s) { if(size()<n) push_back(s); else if(size()>n) { for(auto p=elements+n;p!=first_free;) alloc.destroy(p++); first_free=elements+n; } }