【STL】之Vector的模拟实现

一:迭代器失效?

前面我们了解迭代器其实就是智能指针,可以通过运算符的操作来实现接口函数,但有时有会存在安全隐患。这就是我们常说的迭代器失效。所谓的迭代器失效其实是找某个位置的元素,删除,然后再通过operator++,operator--访问下一个元素,会出现野指针造成崩溃的问题;
如下:
#include<iostream>
#include<list>
using namespace std;
void TestList()
{
    list<int> l;
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);

    list<int>::iterator it = l.begin();

    while (it!=l.end())
    {
        if (*it % 2 == 0)
        {
            l.erase (it);
        }
        ++it;
    }
    cout << endl;
}

我们分析程序为什么会挂掉,我们知道it是一个指针,当执行erase函数时,会将当前的指针释放掉,而it又要和下一个指针链上,这样就会出现一个非法的指针指向一个合法的指针,也就是常说的野指针的问题,从而导致内存崩溃,那么怎么才能防止野指针呢?
void TestList()
{
    list<int> l;
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    l.push_back(4);

    list<int>::iterator it = l.begin();

    while (it!=l.end())
    {
        if (*it % 2 == 0)
        {
            it = l.erase (it);
        }
        else
        {
            ++it;
        }
    }
    cout << endl;
}

我们的方法时先把当前位置的元素删除,然后返回下一个迭代器,再通过operator++,或者operator--访问下一个元素。结果显示如下:

二:resize()函数和reseve()函数的区别:

我们先看resize函数:
void TestVector()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    vector<int> ::iterator it = v.begin();
    while (it!=v.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    v.resize(2);
    cout << "size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.resize(4);
    cout << "size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.resize(6);
    cout << "size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
}

为什么会出现这种结果?我们看看STL中是如何解释的。
在STL中resize()函数的作用是改变vector元素的个数:
主要有三层含义:
1:如果n比vector容器的size小,结果size减小到n,然后删除n之后的数据。
2:如果n比vector容器的size大,扩展空间,然后在size后面插入元素并且初始化,否则初始化为缺省值。
3:如果n比vector容器的capacity还要大,自动进行内存分配。
reseve()函数:
void TestVector()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    vector<int> ::iterator it = v.begin();
    while (it!=v.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    v.reserve(2);
    cout << "size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.reserve(4);
    cout << "size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.reserve(6);
    cout << "size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
}

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

三.STL中Vector的模拟实现

.h文件
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
template <class T>
class Vector
{
public:
    typedef T* Iterator;
    typedef T* ConstIterator;
    Vector()
        :_start(NULL)
        ,_finsh(NULL)
        ,_EndOfStorage(NULL)
    {}
     //v1(v2)
    Vector(const Vector &v)
        :_start(NULL)
        , _finsh(NULL)
        , _EndOfStorage(NULL)
    {
        size_t size = Size();
        size_t capacity = Capacity();
        T*tmp = new T[capacity];//开辟空间
        for (size_t i = 0; i < size; ++i)//拷贝数据
        {
            //memcpy在string会出现浅拷贝
            tmp[i] = v._start[i];
        }
        delete[]_start;
        _start = tmp;
        _finsh = v._finsh;
        _EndOfStorage = v._EndOfStorage;
    }
    //v1 = v3
    Vector<T>&operator = (Vector<T>&v)
    {
        swap(_start, v._start);
        swap(_finsh, v._finsh);
        swap(_EndOfStorage, v._EndOfStorage);
        return *this;
    }
    ~Vector()
    {
        _Destroy();
    }

void PushBack(const T& val)
{
        _Expand(Capacity()*2 + 3);
        *_finsh = val;
        ++_finsh;
}
void PopBack()
{
    Erase(End());
}

//改变容量
void Reserve(size_t n)
{
        assert(n > 0);

        if (_finsh == _EndOfStorage)
        {
            _Expand(n);
        }
}
//改变数组的个数
void Resize(size_t n, T val = T())
{
    if (n > Capacity())
    {
        _Expand(n);
    }
    if (n < Size())
    {
        //--_Size();
        _finsh = _start + n;
    }
    else
    {
        for (size_t i = Size(); i < Capacity(); ++i)
        {
            _start[i] = val;
        }
    }
}
//随机位置的插入
void Insert(Iterator pos,size_t n, const T&x)
{
    size_t sub = pos - strat;//当前位置与_start的相对位置
    _Expand(n);//检查容量
    size_t pos = _start + pos;//更新pos防止迭代器失效
    Iterator it = _finsh;
    while (pos < it)
    {
        *it = *(it - 1);
        --it;
    }
    *pos = x;
    ++_finsh;
}
//随机位置的删除
void Erase(Iterator pos)
{
    if (Empty())
    {
        assert(false);
        return;
    }
    Iterator Cur = pos;
    Iterator end = End();
    while (Cur < end)
    {
        *Cur = *(Cur + 1);
        ++Cur;
    }
    --_finsh;
}
void _Destroy()
{
    if (_start != NULL)
    {
        delete[]_start;
    }
    _start = _finsh = _EndOfStorage = NULL;
}
size_t Size()
{
    return _finsh - _start;
}
size_t Capacity()
{
    return _EndOfStorage - _start;
}
//迭代器的操作
public:
    Iterator  Begin()
    {
        return _start;
    }
    Iterator End()
    {
        return _finsh;
    }
    bool Empty() const
    {
        return Begin() == End();
    }
    ConstIterator  Begin() const
    {
        return _start;
    }
    ConstIterator End() const
    {
        return _finsh;
    }
    T& operator[](size_t indes)
    {
        assert(indes < Size());
        return  _start[indes];
    }
    const T& operator[](size_t indes) const
    {
        assert(indes < Size());
        return  _start[indes];
    }
//增容
protected:
void _Expand(size_t n)
{
    assert(n > 0);
    assert(n > Capacity());
    T*tmp = new T[n];
    if (_start)
    {
        //memcpy()(string)存在浅拷贝
       for (size_t i = 0; i < Size(); ++i)
      {
            tmp[i] = _start[i];
       }
      delete[] _start;
    }
    size_t size = Size();
    _start = tmp;
    _finsh = _start + size;
    _EndOfStorage = _start + n;
}
protected:
        Iterator _start;
        Iterator _finsh;
        Iterator _EndOfStorage;
};
测试函数
cpp文件
#include"Vector.h"
void PrintVector(const Vector<int> &v)
{
    Vector<int> ::ConstIterator it = v.Begin();
    while (it != v.End())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}
void TestVector()
{
    Vector<int> v;
    v.PushBack(1);
    v.PushBack(2);
    v.PushBack(3);
    v.PushBack(4);
    PrintVector(v);


    v.PopBack();
    v.PopBack();
    v.PopBack();
    v.PopBack();
    PrintVector(v);
}
int main()
{
    TestVector();
    system("pause");
    return 0;
}
在这里面尤其注意的是在随机位置的插入Insert() 函数和随机位置的删除Erase() 函数:
1:此时的pos是个迭代器;挪动数据通过指针实现;
2:在进行插入时要进行容量检查,删除时要进行判空。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值