【C++】vector的底层剖析以及模拟实现

简介: 【C++】vector的底层剖析以及模拟实现

一、vector的简单认识

      vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。

二、vector的简单模拟实现

vector的底层我模仿库里面的实现方法,设计了三个指针:

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

以及正向迭代器,不可修改迭代器,各种构造函数,析构函数, reserve(预开辟出空间,字符串还是原来的大小(一般不缩容))resize(将vector设定为指定大小,字符串占满所开辟的空间)push_back(尾插)pop_back(尾删)insert(在pos位置上插入x,并返回pos位置的地址)erase(删除pos位置上的元素,并返回该位置的地址)。

注意事项:迭代器失效

      以reserve为例,当reserve开辟新空间时会释放原来的旧空间,导致_start,_finish都不是原来的_start,_finish,如果此时贸然对_start,_finish进行运算,很可能会导致程序崩溃。我的做法是先记录下原来vector的长度,再用_start加上记录下的长度,就能得到正确的_finish,具体实现见下面代码。

完整代码

#pragma once
#include <iostream>
using namespace std;
namespace sxb
{
    template<class T>
    class vector
    {
    public:
        typedef T* iterator;
       
    private:
        iterator _start; // 指向数据块的开始
        iterator _finish; // 指向有效数据的尾
        iterator _endOfStorage; // 指向存储容量的尾
    public:
        // Vector的迭代器是一个原生指针
       
        typedef const T* const_iterator;
        iterator begin()
        {
            return _start;
        }
        iterator end()
        {
            return _finish;
        }
        const_iterator cbegin() const
        {
            return _start;
        }
        const_iterator cend() const
        {
            return _finish;
        }
            // construct and destroy
        vector() {}
        
        //构造一个长度为n,值为value的vector
        vector(int n, const T& value = T())
        {
            _start = new T[n+1];
            _finish = _start + n;
            _endOfStorage = _start + n;
            for (int i = 0; i < n; i++)
            {
                *(_start + i) = value;
            }
        }
            template<class InputIterator>
            //利用一段迭代器构造
            vector(InputIterator first, InputIterator last)
            {
                int len = 0;
                while (first != last)// 1 2 3 4 5
                {
                    len++;
                    first++;
                }
                len++;
                _start = new T[len+1];
                memcpy(_start, first, sizeof(T) * len);
                _finish = _start + len;
                _endOfStorage = _finish;
            }
            //利用已有的vector构造
            vector(const vector<T>& v)
            {
                _start = new T[v.size() + 1];
                memcpy(_start, v.cbegin(), sizeof(T) * v.size());
                _finish = _start + v.size();
                _endOfStorage = _finish;
            }
            //赋值构造
            vector<T>& operator= (vector<T> v)
            {
                vector(v);
                return *this;
            }
            ~vector()
            {
                delete[] _start;
                _finish = nullptr;
                _endOfStorage = nullptr;
            }
            // capacity
            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 + 1];
                    //迭代器失效处理
                    int oldnum = _finish - _start;
                    memcpy(tmp, _start, sizeof(T) * (_finish - _start));
                    delete[] _start;
                    _start = tmp;
                    _finish = _start + oldnum;
                    _endOfStorage = _start + n;
                }
            }
            void resize(size_t n, const T& value = T())
            {
                if (n > capacity())
                {
                    int oldnum = _finish - _start;
                    reserve(n);
                    while ((_start + oldnum) != _endOfStorage)
                    {
                        *(_start + oldnum) = value;
                        oldnum++;
                    }
                }
                else
                {
                    _finish = _start + n;
                }
            }
            ///access///
            T& operator[](size_t pos)
            {
                return *(_start + pos);
            }
            const T& operator[](size_t pos)const
            {
                return *(_start + pos);
            }
            ///modify/
            void push_back(const T& x)
            {
                if (size() == capacity())
                {
                    reserve(capacity() == 0 ? 4 : capacity() * 2);
                }
                _start[size()] = x;
                _finish++;
            }
            void pop_back()
            {
                _finish--;
            }
            void swap(vector<T>& v)
            {
                std::swap(_start, v._start);
                std::swap(_finish, v._finish);
                std::swap(_endOfStorage, v._endOfStorage);
            }
            //迭代器失效
            iterator insert(iterator pos, const T& x)
            {
                int len = 0;
                while (pos != _start)
                {
                    len++;
                    pos--;
                }
                if (size() == capacity())
                {
                    reserve(capacity() == 0 ? 4 : capacity() * 2);
                }
                iterator endfinish = _finish;
                while (endfinish > _start + len)
                {
                    *(endfinish) = *(endfinish - 1);
                    endfinish--;
                }
                *endfinish = x;
                _finish++;
                return _start + len;
            }
            iterator erase(iterator pos)
            {
                iterator pos2 = pos;
                while (pos != _finish - 1)
                {
                    *pos = *(pos + 1);
                    pos++;
                }
                _finish--;
                return pos2;
            }
    };
}
相关文章
|
6天前
|
C++
c++的学习之路:13、vector(2)
c++的学习之路:13、vector(2)
24 0
|
6天前
|
编译器 C++
C++:vector增删查改模拟实现
C++:vector增删查改模拟实现
57 0
|
6天前
|
编译器 C++ 容器
【C++练级之路】【Lv.7】【STL】vector类的模拟实现
【C++练级之路】【Lv.7】【STL】vector类的模拟实现
|
6天前
|
存储 算法 测试技术
C++:Vector的使用
C++:Vector的使用
|
6天前
|
存储 算法 C++
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
74 1
|
6天前
|
编译器 C++ Windows
【C++】vector问题解决(非法的间接寻址,迭代器失效 , memcpy拷贝问题)
不使用memcpy函数不就可以了,然后我们使用简单粗暴的赋值拷贝,这样就不会发生浅拷贝问题了!!!
18 1
|
6天前
|
算法 C++ 容器
【C++/STL】vector(常见接口、模拟实现、迭代器失效)
【C++/STL】vector(常见接口、模拟实现、迭代器失效)
12 0
|
6天前
|
存储 缓存 编译器
【C++进阶(五)】STL大法--list模拟实现以及list和vector的对比
【C++进阶(五)】STL大法--list模拟实现以及list和vector的对比
|
6天前
|
编译器 C++
【C++进阶(三)】STL大法--vector迭代器失效&深浅拷贝问题剖析
【C++进阶(三)】STL大法--vector迭代器失效&深浅拷贝问题剖析
|
6天前
|
存储 C语言 C++
【C++进阶(二)】STL大法--vector的深度剖析以及模拟实现
【C++进阶(二)】STL大法--vector的深度剖析以及模拟实现