模拟实现STL中的vector

本文通过模拟实现STL中的Vector容器,详细解析Vector的工作原理及其关键特性,包括动态空间分配、迭代器使用、插入删除操作及容量调整等功能。

在之前的文章模拟实现源码剖析了STL中的List,这篇文章模拟STL中的vector.
模拟实现STL中的list
《STL源码剖析》中对vector的描述是这样的:
vector的数据安排以及操作方式,与array非常相似。两者的唯一区别在于空间运用的灵活性。array是静态空间,一旦配置了就不能改变。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。
vector的实现技术,关键在于其对大小的控制以及重新分配时的数据移动效率。

vector的迭代器是普通指针
vector维护的是一个线性连续空间,所以不论其元素类型是什么,普通指针都可以作为vector的迭代器而满足所有必要条件,因为vector所需要的操作行为,如operator*,operator->,operator++,operator–等,普通指针天生就具备,vector支持随机存取,而普通指针正有着这样的能力。

#include<iostream>
#include<assert.h>
using namespace std;

template<class T>
class Vector
{
protected:
    typedef T* Iterator;
    typedef const T* ConstIterator;
public:
    Vector()
        :_start(NULL)
        , _finish(NULL)
        , _endofstorage(NULL)
    {}

    Vector<T>&operator = (Vector<T>&v)
    {
        if (_start != v._start)
        {
            swap(_start, v._start);
            swap(_finsh, v._finsh);
            swap(_EndOfStorage, v._EndOfStorage);
        }
        return *this;
    }

    Vector(const Vector<T>& v)
        :_start(NULL)
        , _finish(NULL)
        , _endofstorage(NULL)
    {
        size_t size = Size();
        size_t capacity = Capacity();
        T* tmp = new T[capacity];
        if (_start)
        {
            for (size_t i; i < Size(); ++i)
            {
                tmp[i] = v._start[i];
            }
            delete[] _start;
        }
        _start = tmp;
        _finish = v._finish;
        _endofstorage = v._endofstorage;
    }

//随机插入
    void Insert(Iterator pos, const T& x)
    {
        if (_finish == _endofstorage)
        {
            _Expand(Capacity() * 2 + 3);
        }
        for (Iterator tmp = End(); tmp != pos; tmp--)
        {
            *tmp = *(tmp - 1);
        }
        *pos = x;
        _finish++;
    }

//随机删除
    void Erase(Iterator pos)
    {
        Iterator end = End();
        for (Iterator tmp = pos; tmp != --end; ++tmp)
        {
            *tmp = *(tmp + 1);
        }
        --_finish;
    }

    //改变容量
    void Reserve(size_t n)
    {
        assert(n > 0);
        if (n > Capacity())
        {
            _Expand(n);//扩容
        }
    }

    //改变元素个数
    void Resize(size_t n, const T& x = 0)
    {
        size_t size = Size();
        size_t capacity = Capacity();
        if (n > Capacity())
        {
            _Expand(n);
            for (size_t i = 0; i <= n-size; ++i)
            {
                Insert(Begin()+size+i, x);
            }
        }
        else if (n > Size())
        {
            for (size_t i = 0; i <= n-size; ++i)
            {
                Insert(Begin()+size+i, x);
            }
        }
        else if (n < size)
        {
            _finish = _start + n;
        }

    }

    void PushBack(const T& x)
    {
        if (_finish == _endofstorage)
        {
            _Expand(Capacity() * 2 + 3);
        }
        Insert(End(), x);
    }

    void PopBack()
    {
        Iterator end = End();
        Erase(--end);
    }

    Iterator Begin()
    {
        return _start;
    }

    Iterator End()
    {
        return _finish;
    }

    size_t Size()
    {
        return (End() - Begin());
    }

    size_t Capacity()
    {
        return (_endofstorage - _start);
    }

    bool Empty()
    {
        return _start == _finish;
    }

//要支持[]
    T& operator[](size_t n)
    {
        return _start + n;
    }

    T& Front()const
    {
        return *Begin();
    }

    T& Back()const
    {
        return *End();
    }

    void Print()
    {
        for (size_t i = 0; i < Size(); i++)
        {
            cout << _start[i] << " ";
        }
        cout << endl;
    }
protected:
    void _Expand(size_t n)
    {
        assert(n > 0);
        assert(n > Capacity());
        T* tmp = new T[n];
        if (_start)
        {
            for (size_t i = 0; i < Size(); ++i)
            {
                tmp[i] = _start[i];
            }
            delete[] _start;
        }
        size_t size = Size();
        _start = tmp;
        _finish = _start + size;
        _endofstorage = _start + n;
    }

protected:
    Iterator _start;//表示目前使用空间的头
    Iterator _finish;//表示目前使用空间的尾
    Iterator _endofstorage;//表示目前可用空间的尾
};

void Test()
{
    Vector<int> v;
    v.PushBack(1);
    v.PushBack(2);
    v.PushBack(3);
    v.PushBack(4);
    v.PushBack(5);
    v.Resize(8,6);
    //v.Reserve(10);
    //v.PopBack();
    v.Print();
}

在STL中resize()函数的作用是改变vector元素的个数:
主要有三层含义:
1:如果n比vector容器的size小,结果size减小到n,然后删除n之后的数据。
2:如果n比vector容器的size大,扩展空间,然后在size后面插入元素并且初始化,否则初始化为缺省值。
3:如果n比vector容器的capacity还要大,自动进行内存分配。

在STL中reserve()的作用是改变容量:
1:如果n的大小比vector的容量大,开空间增容到n
2:其他的情况,没有开空间,vetor的容量不受影响。而且size的值没有变化。
当然使用reserve的优点是减少开销。
总结resize()函数时改变数组的个数并对其初始化,而reserve()函数只是改变容量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值