不使用模板,建立一个用于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;
}