vector

vector的实现

基础框架

class vector
{
public:
    // 重命名几种类型
    typedef T value_type;
    typedef value_type* iterator;
    typedef const value_type* const_iterator;
    typedef value_type& reference;
    typedef const value_type& const_reference;
private:
    // 几个迭代器
    iterator _start;
    iterator _finish;
    iterator _end_of_storage;
public:
    iterator begin() { return _start; }
    iterator end() { return _finish; }
    const_iterator begin() const { return _start; }
	const_iterator end() const { return _finish; }

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

    void reserve(size_t n)
    {
        if (n > capacity())
        {
            value_type* tmp = new value_type[n];
            size_t old_size = size();	// 这里需要有一个old_size,防止后面更新_start后_finish为0
            if (_start)
            {
                // memcpy(tmp, _start, sizeof(value_type) * old_size);
                for (size_t i = 0; i < old_size; ++i)
                {
                    tmp[i] = _start[i];
                }
            }
            delete[] _start;
            // 调整迭代器
            _start = tmp;
            _finish = _start + old_size;
            _end_of_storage = _start + n;
        }
    }

    reference operator[](size_t n) { return *(begin() + n); }
    const_reference operator[](size_t n) const { return *(begin() + n); }

    void push_back(const T& x)
    {
        // 空间满了要扩容
        if (_finish == _end_of_storage)
            capacity() == 0 ? reserve(4) : reserve(2 * capacity());
        *_finish = x;		// 注意这里有个 * 解引用
        ++_finish;
    }

    void pop_back()
    {
        assert(_start < _finish);
        --_finish;
    }

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

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

insert和erase

void insert(iterator pos, const value_type& x)
{
    assert(pos >= _start);
    assert(pos <= _finish);
    // 空间满了要扩容
    if (_finish == _end_of_storage)
    {
        // 保存一下pos的位置,防止扩容后pos变成野指针导致迭代器失效
        size_t len = pos - _start;
        capacity() == 0 ? reserve(4) : reserve(2 * capacity());
        pos = _start + len;
    }
    // 挪动数据
    iterator end = _finish;
    while (end != pos)
    {
        *end = *(end - 1);
        --end;
    }
    *pos = x;
    ++_finish;
}

iterator erase(iterator pos)
{
    assert(pos >= _start);
    assert(pos < _finish);		// 这里没有等于
    iterator cur = pos;
    while (cur != _finish)
    {
        *cur = *(cur + 1);
        ++cur;
    }
    --_finish;

    return pos;		// 返回删除位置下一个的迭代器
}
测试insert迭代器失效
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
auto p = find(v.begin(), v.end(),3);

if (p != v.end())
{
    v.insert(p, 30);	// 如果insert不处理就会导致迭代器失效
    // 使用insert之后,不要再继续访问
    // v.insert(p, 400);
}

在这里插入图片描述

erase的问题
// 测试erase,假设想要删除vector中所有的偶数
void test_erase()
{
    v.push_back(1);
    v.push_back(2);
    v.push_back(4);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    vector<int>::iterator it = v.begin();
    while (it != v.end())
    {
        if ((*it) % 2 == 0)
        {
            v.erase(it);
        }
        ++it;
    }
}

上面的代码结果不对(1 4 3 5),当输入数据为1 2 3 4的时候甚至会崩溃,原因在下面

在这里插入图片描述

所以,stl的erase提供一个返回值,返回删除位置的下一个元素的迭代器,因此,下面的代码才是对的

while (it != v.end())
{
    if ((*it) % 2 == 0)
        it = v.erase(it);
    else
        ++it;
}

总结:insert,erase pos位置后,不要再次访问pos,可能会出现各种出乎意料的结果,这就是迭代器失效
迭代器失效解决办法:在使用前,对迭代器重新赋值即可

拷贝构造函数

// 传统的拷贝构造函数
// v(v1)
vector(const vector<value_type>& v1)
{
    _start = new value_type[v1.size()];		// v1的capacity()也可以
    //memcpy(_start, v1._start, v1.size() * sizeof(value_type));
    // 需要这样写,要不然vector是二维数组的时候会报错
    for (size_t i = 0; i < v1.size(); ++i)
    {
        _start[i] = v1[i];		// T对象是自定义类型时,调用T对象的opeartor=
    }
    _finish = _start + v1.size();
    _end_of_storage = _start + v1.size();
}
// 另一种写法
// v(v1)
vector(const vector<value_type> &v1)
    :_start(nullptr)
	,_finish(nullptr)
    ,_end_of_storage(nullptr)
    {
        reserve(v1.size());
        for (const auto& e : v1)	// 这里最好要有引用
            push_back(e);
    }
// 若想实现现代写法, 需要再写一个有参构造函数
// 带迭代器区间的构造函数
// 模板的作用是让传进来的迭代器可以是任意容器的迭代器
template<typename InputIterator>	
vector(InputIterator first, InputIterator last)
:_start(nullptr)
    ,_finish(nullptr)
    ,_end_of_storage(nullptr)
{
    while (first != last)
    {
        push_back(*first);
        ++first;
    }
}
// 现代写法
void swap(vector<value_type>& v)
{
    ::swap(_start, v._start);
    ::swap(_finish, v._finish);
    ::swap(_end_of_storage, v._end_of_storage);
}

vector(const vector<value_type> &v1)
    :_start(nullptr)
        ,_finish(nullptr)
        ,_end_of_storage(nullptr)
{
    vector<value_type> tmp(v1.begin(), v1.end());
    swap(tmp);
}

赋值构造函数

// 赋值构造函数-传统写法
// v = v1
vector<value_type>& operator=(vector<value_type> v1)
{
    if (this != &v1)
    {
        // 删除旧的空间
        delete[] _start;
        // 开新空间
        _start = new value_type[v1.size()];
        // 拷贝数据
        memcpy(_start, v1._start, sizeof(value_type) * v1.size());
        _finish = _start + v1.size();
        _end_of_storage = _start + v1.capacity();
    }
    return *this;
}
// 赋值构造函数,现代写法
vector<value_type>& operator=(vector<value_type> v)		// 需要先写完拷贝构造
{
    swap(v);
    return *this;
}

resize()

void resize(size_t n, value_type val = value_type())
{
    // 扩容
    if (n > capacity())
        reserve(n);
    // 如果大于size(),就初始化数据
    if (n > size())
    {
        while (_finish != _start + n)
        {
            *_finish = val;
            ++_finish;
        }
    }
    // n<size(), 删除数据
    else
    {
        _finish = _start + n;
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值