美文网首页
VecStr(模仿vector容器)

VecStr(模仿vector容器)

作者: 峡迩 | 来源:发表于2017-09-09 19:12 被阅读0次
// Vecstr.cpp :模拟vector容器,但是仅仅对string有效!
//

#include "stdafx.h"
#include<string>
#include<iostream>
#include<vector>
#include<memory>
#include<utility>
#include<algorithm>

using namespace std;

class VecStr
{
public:
    VecStr():elements(nullptr),first_free(nullptr),cap(nullptr) {}

    //VecStr(const VecStr &rh):elements(rh.elements),first_free(rh.first_free),cap(rh.cap){}这没有拷贝元素!
    VecStr(const VecStr &rh)
    {
        auto newdata = alloc_n_copy(rh.begin(), rh.end());
        elements = newdata.first;
        first_free = cap = newdata.second;
    }
    VecStr operator=(const VecStr &rh)
    {
        auto data = alloc_n_copy(rh.begin(), rh.end());//拷贝
        free();     //释放原对象!alloc申请的两块空间不相同,所以可以释放!
        elements = data.first;
        first_free = cap = data.second;
        return *this;
    }

    //只有当一个类没有为自己定义任何拷贝控制成员,且类的每个非static数据成员都可以移动,编译器才会自动合成移动构造函数和赋值函数。对于所有内置成员,都含有移动操作!

    VecStr(const VecStr &&rh) noexcept:elements(rh.elements),first_free(rh.first_free),cap(rh.cap)
    {
        elements = first_free = cap = nullptr;          //确保原对象不再指向移动后的源!
    }
    VecStr& operator=(const VecStr &&rh) noexcept
    {
        if (&rh != this)
        {
            free();         //释放现有资源
            elements = rh.elements;
            first_free = rh.first_free;
            cap = rh.cap;
            elements = first_free = cap = nullptr;
        }
        return *this;
    }
    ~VecStr() { free(); }

    void push_back(const string &s);
    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; }


private:
    string *elements;
    string  *first_free;
    string *cap;
    static std::allocator<std::string> alloc;       //此为声明语句
    pair<string*, string*> alloc_n_copy(const string *lh, const string *rh);
    void check_n_alloc()
    {
        if (size() == capacity())
        {
            reallocate();       //重新分配内存!
        }
    }
    void free();
    void reallocate();
};

void VecStr::push_back(const string &s)
{
    check_n_alloc();
    alloc.construct(first_free++,s);        //在first_free处构造字符串s!
}
pair<string*, string*> VecStr::alloc_n_copy(const string *lh, const string *rh)
{
    auto data = alloc.allocate(rh - lh);            //拷贝lh至rh范围的元素;
    return { data,uninitialized_copy(lh,rh,data) };//uninitialized_copy将lh至rh范围内的元素拷贝至data!返回首地址data和尾地址!
}
void VecStr::free()
{
    if (elements)
    {
        for (auto p = first_free; p != elements;)
            alloc.destroy(--p);
        alloc.deallocate(elements, cap - elements);
    }
}
void VecStr::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)//此部分内容可以改为auto dest=uninitialized_copy(make_move_iterator(begin()),make_move_iterator(end()),first)  ,返回first_free位置!(make_move_iterator将普通迭代器转为移动迭代器!)
        alloc.construct(dest++, std::move(*elem++));
    free();//此时释放的什么?
    elements = newdata;
    first_free = dest;
    cap = elements + newcapacity;
}

allocator<std::string> VecStr::alloc;
//静态成员不属于类的任何一个对象,一般来说我们不能在类内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,一个静态成员只能定义一次!
//静态成员在类内初始化只允许static constexpr int period=30;即是在类内初始化了,也需要在类外定义以下该成员constexpr int Account::period!另外,静态成员可以在类中作为函数的实参!
int main()
{

    //const vector<string> v = { "string" ,"a"};
    allocator<string> a;
    auto b1=a.allocate(200);
    //a.construct(b1, "asd");
    //a.construct(++b1, "adsf");

    auto b2 = a.allocate(200);
    cout << b1-b2;
    return 0;
}

相关文章

网友评论

      本文标题:VecStr(模仿vector容器)

      本文链接:https://www.haomeiwen.com/subject/sujajxtx.html