【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;
            }
    };
}
相关文章
|
4月前
|
存储 编译器 C++
【C++】vector介绍+模拟实现
【C++】vector介绍+模拟实现
|
23天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
48 4
|
5天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
23 0
|
9天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
18 0
|
2月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
26 1
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化2
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
75 6
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化1
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
88 7
|
2月前
|
编译器 C++
【C++】—— vector模拟实现
【C++】—— vector模拟实现
|
2月前
|
编译器 C语言 C++
【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
58 3
|
2月前
|
C++
【C++】C++ STL探索:Vector使用与背后底层逻辑(三)
【C++】C++ STL探索:Vector使用与背后底层逻辑