vector 模拟实现

vector 模拟实现

vector介绍

vector是表示可变大小数组的序列容器
  就像数组一样,vector也采用连续的存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

vector 基本框架

namespace my_vector
{
    template<class T>
    class vector
    {
    public:
        typedef T* iterator;
        typedef const T* const_iterator;
        iterator begin();
        iterator end();
        const_iterator cbegin();
        const_iterator cend() const;
        vector();
        vector(int n, const T& value = T());
        template<class InputIterator>
        vector(InputIterator first, InputIterator last);
        vector(const vector<T>& v);
        vector<T>& operator= (vector<T> v);
        ~vector();
        size_t size() const;
        size_t capacity() const;
        void reserve(size_t n);
        void resize(size_t n, const T& value = T());
        T& operator[](size_t pos);
        const T& operator[](size_t pos)const;
        void push_back(const T& x);
        void pop_back();
        void swap(vector<T>& v);
        iterator insert(iterator pos, const T& x);
        iterator erase(Iterator pos);
    private:
        iterator _start; // 指向数据块的开始
        iterator _finish; // 指向有效数据的尾
        iterator _endOfStorage; // 指向存储容量的尾
    };
}

默认成员函数

构造函数

构造一个空vector,size 和 capacity 为 0,将 _start,_finish, _endofstorage 都置为空指针即可

vector() :_start(nullptr), _finish(nullptr), _endofStorage(nullptr) {}

用n个 val 值进行初始化,可以复用 resize 接口,但要注意调用resize()接口需要计size(),capacity(),所以要将成员变量进行初始化

vector(int n, const T& value = T())
{
    resize(n, value);
}

用迭代器区间进行初始化,由于不同类型的容器迭代器类型不同,设计成函数模板,将区间内的内容尾插入vector即可,但注意调用push_back接口通过 _finish == _endofstorage 判断是否满,需要初始化

//迭代器
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
    reserve(last - first);
    while (first != last)
    {
        *_finish++ = *first++;
    }
}

拷贝构造函数

vector(const vector<T>& v)
{
    reserve(v.capacity());
    T* first = v._start;
    while (first != v._finish)
    {
        *_finish++ = *first++;
    }
}

赋值构造函数

vector<T>& operator= (vector<T> v)
{
    swap(v);
    return *this;
}

析构函数

~vector()
{
    if (_start)
        delete[]_start;
    _start = nullptr;
    _finish = nullptr;
    _endofStorage = nullptr;
}

扩容操作

reserve()

  • n >= capacity,将capacity扩大到n或大于n。
  • n < capacity,直接出函数
void reserve(size_t n)
{
    if (n > capacity())
    {
        T* tmp = new T[n];
        size_t num = size();
        if (_start)
        {
            for (size_t i = 0; i < num; i++)
            {
                tmp[i] = _start[i];
            }
            delete[] _start;
        }
        _start = tmp;
        _finish = _start + num;
        _endofStorage = _start + n;
    }
}

实现步骤:

  • 新开辟一块空间,若容器为空,将_start,_finish指向新开辟空间的首元素地址, _endofstorage指向新开辟空间的最后一个元素下一个位置
  • 若容器不为空,将数据拷贝到新空间,释放掉旧空间,更新_start,_finish, _endofstorage的位置

注意 : 将数据拷贝到新空间,不能用memcpy,使用memcpy函数以后,新开辟空间里的元素和原空间里的元素所指向的内存空间是一样的,当旧空间被释放时,会调用自定义类型的析构函数,从而使得新开辟空间里的元素指向的内存空间也被释放掉了

resize()

  • n < size : 直接将 _finish = _start + n (将有效数据长度缩小)即可
  • size < n <= capacity :我们将有效数据的长度增加到 n,增加出来的有效数据内容是val
  • n > capacity : 先调用上面的 reserve 函数进行增容,再将有效数据的长度增加到 n,增加出来的有效数据内容是val。
void resize(size_t n, const T& value = T())
{
    size_t num = size();
    if (n > num)
    {
        reserve(n);
        for (size_t i = num; i < n; i++)
        {
            _start[i] = value;
        }
    }
    _finish = _start + n;
}

尾插&尾删

push_back

  • 尾插入数据,首先要检查是否已满
void push_back(const T& x)
{
    if (size() == capacity())
        reserve(capacity() == 0 ? 4 : capacity() * 2);
    *_finish++ = x;
}

pop_back

  • 尾删时,首先判断容器是否为空

void pop_back()
{
    if (size() > 0)
        _finish--;
}

插入

insert()

  • 容量不够,先增容,增容之前先记录下 pos - _start 的值,否则增容之后,pos 还指向原来已经被释放的空间
  • 将 pos 位置往后的数据往后挪动一位,在pos位置插入值val
iterator insert(iterator pos, const T& x)
{

    assert(pos >= _start && pos <= _finish);
    if (_finish == _endofStorage)
        reserve(capacity() == 0 ? 4 : capacity() * 2);
    T* finish = _finish;
    while (finish > pos)
    {
        *finish = *(finish - 1);
        finish--;
    }
    *pos = x;
    _finish++;
    return pos;
}

删除

erase()
容器若为空,则做断言处理,若不为空,将pos位置往后的数据向前挪动一位

iterator erase(iterator pos)
{
    assert(pos >= 0 && pos < _finish);
    T* _pos = pos;
    while (_pos < _finish - 1)
    {
        *_pos = *(_pos + 1);
        _pos++;
    }
    _finish--;
    return pos;
}

运算符重载

T& operator[](size_t pos)
{
    assert(pos < size());
    return _start[pos];
}

const T& operator[](size_t pos)const
{
    assert(pos < size());
    return _start[pos];
}

迭代器

begin()返回第一个元素的地址,end()返回最后一个元素下一位置的地址;

非const 迭代器

iterator begin()
{
    return _start;
}

iterator end()
{
    return _finish;
}

const 迭代器

为了让const对象调用,加入const版本的begin()和end();

const_iterator cbegin()
{
    return _start;
}

const_iterator cend() const
{
    return _finish;
}

其他辅助函数

size()
返回容器中有效数据的个数

size_t size() const
{
    return _finish - _start;
}

capacity()
返回容器的容量

size_t capacity() const
{
    return _endofStorage - _start;
}

void swap(vector<T>& v)
{
    T* tmp = v._start;
    v._start = _start;
    _start = tmp;

    tmp = v._finish;
    v._finish = _finish;
    _finish = tmp;

    tmp = v._endofStorage;
    v._endofStorage = _endofStorage;
    _endofStorage = tmp;
}

代码总览

#include<iostream>
#include<assert.h>

using std::cout;
using std::cin;
using std::endl;
namespace my_vector
{

    template<class T>
    class vector
    {
    private:
        typedef T* iterator;
        iterator _start; // 指向数据块的开始
        iterator _finish; // 指向有效数据的尾
        iterator _endofStorage; // 指向存储容量的尾

    public:
        typedef T* iterator;

        typedef const T* const_iterator;

        iterator begin()
        {
            return _start;
        }

        iterator end()
        {
            return _finish;
        }

        const_iterator cbegin()
        {
            return _start;
        }

        const_iterator cend() const
        {
            return _finish;
        }

        vector() :_start(nullptr), _finish(nullptr), _endofStorage(nullptr) {}


        vector(int n, const T& value = T())
        {
            resize(n, value);
        }

        template<class InputIterator>

        vector(InputIterator first, InputIterator last)
        {
            reserve(last - first);
            while (first != last)
            {
                *_finish++ = *first++;
            }
        }

        vector(const vector<T>& v)
        {
            reserve(v.capacity());
            T* first = v._start;
            while (first != v._finish)
            {
                *_finish++ = *first++;
            }
        }

        vector<T>& operator= (vector<T> v)
        {
            swap(v);
            return *this;
        }

        ~vector()
        {
            if (_start)
                delete[]_start;
            _start = nullptr;
            _finish = nullptr;
            _endofStorage = nullptr;
        }
        size_t size() const
        {
            return _finish - _start;
        }

        size_t capacity() const
        {
            return _endofStorage - _start;
        }

        void reserve(size_t n)
        {
            if (n > capacity())
            {
                T* tmp = new T[n];
                size_t num = size();
                if (_start)
                {
                    for (size_t i = 0; i < num; i++)
                    {
                        tmp[i] = _start[i];
                    }
                    delete[] _start;
                }
                _start = tmp;
                _finish = _start + num;
                _endofStorage = _start + n;
            }
        }
        void resize(size_t n, const T& value = T())
        {
            size_t num = size();
            if (n > num)
            {
                reserve(n);
                for (size_t i = num; i < n; i++)
                {
                    _start[i] = value;
                }
            }
            _finish = _start + n;
        }

        T& operator[](size_t pos)
        {
            assert(pos < size());
            return _start[pos];
        }

        const T& operator[](size_t pos)const
        {
            assert(pos < size());
            return _start[pos];
        }

        void push_back(const T& x)
        {
            if (size() == capacity())
                reserve(capacity() == 0 ? 4 : capacity() * 2);
                *_finish++ = x;
        }

        void pop_back()
        {
            if (size() > 0)
                _finish--;
        }

        void swap(vector<T>& v)
        {
            T* tmp = v._start;
            v._start = _start;
            _start = tmp;

            tmp = v._finish;
            v._finish = _finish;
            _finish = tmp;

            tmp = v._endofStorage;
            v._endofStorage = _endofStorage;
            _endofStorage = tmp;
        }

        iterator insert(iterator pos, const T& x)
        {

            assert(pos >= _start && pos <= _finish);
            if (_finish == _endofStorage)
                reserve(capacity() == 0 ? 4 : capacity() * 2);
            T* finish = _finish;
            while (finish > pos)
            {
                *finish = *(finish - 1);
                finish--;
            }
            *pos = x;
            _finish++;
            return pos;
        }
        iterator erase(iterator pos)
        {
            assert(pos >= 0 && pos < _finish);
            T* _pos = pos;
            while (_pos < _finish - 1)
            {
                *_pos = *(_pos + 1);
                _pos++;
            }
            _finish--;
            return pos;
        }
    };

}


using namespace my_vector;

int main()
{
    vector<int> ret;
    for(int i=0;i<100;i++)
    ret.push_back(i);

    vector<int> ret1 = ret;
    //vector<int> ret2(100,3);

    vector<int> res(ret.begin(), ret.end());
    for (int i=0;i<20;i++)
    {
        ret1.insert(ret1.begin(),2000);
        
    }
    for (auto e : ret1)
    {
        cout << e << "  ";
    }
}

运行结果

在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ryan.Alaskan Malamute

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值