不使用模板,建立一个用于string的可以自己分配内存的类
StrVec类的设计
使用allocator获得原始内存,并使用allocator的construct成员在内存中创建对象,删除元素使用destroy
使用三个指针依次指向首元素、尾元素和内存末尾的位置,使用alloc静态成员分配StrVec使用的内存,建立四个工具函数,alloc_n_copy会分配内存,并拷贝一个指定范围中的元素,free销毁构造元素并释放内存,chk_n_alloc保证StrVec至少有容纳一个新元素的空间,如果没有空间添加新元素,chk_n_alloc会调用reallocate来分配更多内存,reallocate在内存用完时为StrVec分配新内存
StrVec定义
class StrVec { public: StrVec():elements(nullptr), first_free(nullptr), cap(nullptr){} StrVec(const StrVec&); StrVec& operator=(const StrVec&); ~StrVec(); void push_back(const std::string&); size_t size() const{return first_free - elements}; size_t capacity() const {return cap - elements}; std::string *begin() const {return elements}; std::string *end() const {return firdt_free}; private: static std::allocator<std::string> alloc; void chk_n_alloc() { if (size() == capacity()) reallocate(); } std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std string*); void free(); void reallocator(); std::string *elements; std::string *first_free; std::string *cap; };
使用construct
利用construct创建新对象
void StrVec::push_back(const string &s) { chk_n_alloc(); alloc.construct(first_free++,s); }
alloc_n_copy成员
当进行拷贝时,需要分配新的内存资源,此函数是在返回值中进行拷贝工作的
pair<string* ,string*> StrVec::alloc_n_alloc(const string *b, const string *e) { auto data = alloc.allocate(e - b); return {data, uninitialized_copy(b, e, data)}; }
free成员
void StrVec::free() { if(elements) { for(auto p = first_free; p!=elements;) alloc.destroy(--p); alloc.deallocate(elements, cap - elements); } }
拷贝控制成员
利用前面写好的函数设计拷贝构造函数和重载拷贝运算符
StrVec::StrVec(const StrVec &s) { auto newdata = alloc_n_copy(s.begin(), s.end()); elements = newdata.first; first_free = cap = newdat.second; } StrVec::~StrVec() { free(); } StrVec& StrVec::operator=(const StrVec &rhs) { auto data = alloc_n_copy(rhs.begin(), rhs.end()); free(); elements = data.first; first_free = cap = data.second; return *this; }
reallocate成员
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++)); } free(); elements = newdata; first_free = dest; cap = elements + newcapacity; }