• vector模拟实现


    目录

    vector框架:

    构造函数

    size函数

    capacity函数

    reserve函数

    尾插函数 

    begin()

    end()

    operator[]

    const迭代器

    判断是否为空

    resize函数

    尾删函数

    插入函数:

    扩容导致迭代器失效:

    迭代器不能重复使用

    erase使用之后的迭代器失效问题

    例如:

    swap函数

    clear函数

    析构函数

    拷贝构造

    拷贝构造(现代写法)

    n个val构造

    reserve函数


    vector框架:

    成员变量是三个迭代器: 

    1. #pragma once
    2. namespace zsk
    3. {
    4. template<class T>
    5. class vector
    6. {
    7. public:
    8. typedef T*iterator;
    9. private:
    10. iterator _start;
    11. iterator _finish;
    12. iterator _endofstorage;
    13. };
    14. }

    构造函数

    1. vector()
    2. :_start(nullptr)
    3. , _finish(nullptr)
    4. , _endofstorage(nullptr)
    5. {
    6. }

    size函数

    1. size_t size()const
    2. {
    3. return _finish - _start;
    4. }

    capacity函数

    1. size_t capacity()const
    2. {
    3. return _endofstorage - _start;
    4. }

    reserve函数

    1. void reserve(size_t n)
    2. {
    3. if (n > capacity())
    4. {
    5. size_t oldsize = size();
    6. T*tmp = new T[n];
    7. if (_start)
    8. {
    9. memcpy(tmp, _start, sizeof(T)*oldsize);
    10. delete[] _start;
    11. }
    12. _start = tmp;
    13. _finish = _start + oldsize;
    14. _endofstorage = _start + n;
    15. }
    16. }

    尾插函数 

    1. void Push_back(const T&x)
    2. {
    3. if (_finish == _endofstorage)
    4. {
    5. size_t NewCapacity = capacity() == 0 ? 4 : capacity() * 2;
    6. reserve(NewCapacity);
    7. }
    8. *_finish = x;
    9. ++_finish;
    10. }

    begin()

    1. iterator begin()
    2. {
    3. return _start;
    4. }

    end()

    1. iterator end()
    2. {
    3. return _finish;
    4. }

    operator[]

    1. T&operator[](size_t pos)
    2. {
    3. assert(pos < size());
    4. return _start[pos];
    5. }

    const迭代器

    1. iterator begin()const
    2. {
    3. return _start;
    4. }
    1. iterator end()const
    2. {
    3. return _finish;
    4. }

    判断是否为空

    1. bool empty()const
    2. {
    3. return _start == _finish;
    4. }

    resize函数

    1. void resize(size_t n, T val = T())
    2. {
    3. if (n > capacity())
    4. {
    5. reserve(n);
    6. }
    7. if (n > size())
    8. {
    9. while (_finish > _start + n)
    10. {
    11. *_finish = val;
    12. _finish++;
    13. }
    14. }
    15. else
    16. {
    17. _finsh = _start + n;
    18. }
    19. }

    尾删函数

    1. void pop_back()
    2. {
    3. assert(!empty());
    4. _finish--;
    5. }

    插入函数:

    1. void insert(iterator pos, const T&val)
    2. {
    3. assert(_pos >= _start);
    4. assert(_pos <= _finish);
    5. if (_finish == _endofstorage)
    6. {
    7. size_t NewCapacity = capacity() == 0 ? 4 : capacity() * 2;
    8. reserve(NewCapacity);
    9. }
    10. iterator end = _finish;
    11. while (pos < end)
    12. {
    13. *end = *(end - 1);
    14. --end;
    15. }
    16. *pos = val;
    17. ++_finish;
    18. }

    扩容导致迭代器失效:

     vector使用的扩容是异地扩容,如图所示:

    发生了扩容,新开辟一个空间拷贝数据,释放旧的空间。

     

    pos依旧指向旧空间,这时候旧的空间已经被释放了,导致了pos迭代器失效。

    处理方法:在扩容时记录迭代器的相对位置。

    1. void insert(iterator pos, const T&val)
    2. {
    3. assert(pos>= _start);
    4. assert(pos< _finish);
    5. if (_finish == _endofstorage)
    6. {
    7. size_t len = pos - _start;
    8. size_t NewCapacity = capacity() == 0 ? 4 : capacity() * 2;
    9. reserve(NewCapacity);
    10. pos = _start + len;
    11. }
    12. iterator end = _finish;
    13. while (pos < end)
    14. {
    15. *end = *(end - 1);
    16. --end;
    17. }
    18. *pos = val;
    19. ++_finish;
    20. }

    迭代器不能重复使用

    这里发生的是传值传参,并不会影响外界的it1,虽然我们在内部规避了迭代器失效的问题,但是只要发生了扩容,外部依旧会迭代器失效。

    迭代器返回插入函数:

    1. iterator insert(iterator pos, const T&val)
    2. {
    3. assert(pos>= _start);
    4. assert(pos< _finish);
    5. if (_finish == _endofstorage)
    6. {
    7. size_t len = pos - _start;
    8. size_t NewCapacity = capacity() == 0 ? 4 : capacity() * 2;
    9. reserve(NewCapacity);
    10. pos = _start + len;
    11. }
    12. iterator end = _finish;
    13. while (pos < end)
    14. {
    15. *end = *(end - 1);
    16. --end;
    17. }
    18. *pos = val;
    19. ++_finish;
    20. return pos;
    21. }

    erase函数

    1. void erase(iterator pos)
    2. {
    3. assert(!empty());
    4. assert(pos >= _start);
    5. assert(pos < _finish);
    6. iterator end = _finish-1;
    7. while (pos < end)
    8. {
    9. *(pos) = *(pos + 1);
    10. pos++;
    11. }
    12. __finish;
    13. }

    erase使用之后的迭代器失效问题

    答:erase函数使用之后,迭代器可能会失效,取决于不同的编译器,我们在使用erase之后的迭代器最好不要再使用。

    例如:

    1. int main()
    2. {
    3. /*zsk::func();*/
    4. std::vector<int> v;
    5. v.push_back(1);
    6. v.push_back(2);
    7. v.push_back(3);
    8. v.push_back(4);
    9. v.push_back(5);
    10. v.push_back(6);
    11. std::vector<int>::iterator it1 = v.begin();
    12. if (it1 != v.end())
    13. {
    14. if (*it1 % 2 == 0)
    15. {
    16. it1 = v.erase(it1);
    17. }
    18. else
    19. {
    20. it1++;
    21. }
    22. }
    23. cout << *it1;
    24. return 0;
    25. }

    我们在调用erase函数之后,迭代器it1失效,我们要重新给it1赋值才能使用it1.

    swap函数

    1. void swap(vector&v)
    2. {
    3. std::swap(_start, v._start);
    4. std::swap(_finish, v._finish);
    5. std::swap(_endofstorage, v._endofstorage);
    6. }

    clear函数

    1. void clear()
    2. {
    3. _finish = _start;
    4. }

    析构函数

    1. ~vector()
    2. {
    3. delete[]_start;
    4. _start = _finish = _endofstorage = nullptr;
    5. }

    拷贝构造

    1. template <class InputIterator>
    2. vector(InputIterator first, InputIterator finish)
    3. :_start = nullptr
    4. , _finish = nullptr
    5. , _endofstorage = nullptr
    6. {
    7. while (first != finish)
    8. {
    9. Push_back(*first);
    10. first++;
    11. }
    12. }

    拷贝构造(现代写法)

    1. vector(const vector&v)
    2. :_start = nullptr
    3. , _finish = nullptr
    4. , _endofstorage = nullptr
    5. {
    6. vector tmp(v.begin(), v.end());
    7. swap(tmp);
    8. }

    n个val构造

    1. explicit vector(int n, const T& val = T())
    2. :_start = nullptr
    3. , _finish = nullptr
    4. , _endofstorage = nullptr
    5. {
    6. reserve(n);
    7. for (int i = 0; i < n; i++)
    8. {
    9. Push_back(val);
    10. }
    11. }

    reserve函数

    1. void reserve(size_t n)
    2. {
    3. if (n > capacity())
    4. {
    5. size_t oldsize = size();
    6. T*tmp = new T[n];
    7. for (int i = 0; i < oldsize; i++)
    8. {
    9. tmp[i] = _start[i];
    10. }
    11. delete[] _start;
    12. _start = tmp;
    13. _finish = _start + oldsize;
    14. _endofstorage = _start + n;
    15. }
    16. }

  • 相关阅读:
    <专利>机器人3D视觉快速定位抓取方法及系统
    Linux 串口应用编程
    VUE.js概述——过滤器
    直线导轨坏了可以维修吗?
    SELinux零知识学习二十三、SELinux策略语言之类型强制(8)
    解码器 | 基于 Transformers 的编码器-解码器模型
    115 双周赛
    电流继电器HDL-A/1-110VDC-1
    springboot经典问题总结
    iOS - 多线程-GCD
  • 原文地址:https://blog.csdn.net/qq_66581313/article/details/133983891