• 【STL***vector容器二】


    目录

    push_back和pop_back

    删除元素-erase&clear

    重载运算符

    容器的调整

    swap交换

    总结


    本节分析vector实现删除,交换,插入,重载等操作的实现

    push_back和pop_back

    1. // 如果可用空间还有就调用对象的构造函数并使用空间的尾增加
    2. // 没有空间就重新申请一个更大的空间, 然后进行插入
    3. void push_back(const T& x)
    4. {
    5. // 如果还没有到填满整个数组, 就在数据尾部插入
    6. if (finish != end_of_storage)
    7. {
    8. construct(finish, x);
    9. ++finish;
    10. }
    11. // 数组被填充满, 调用insert_aux必须重新寻找新的更大的连续空间, 再进行插入
    12. else
    13. insert_aux(end(), x);
    14. }
    1. // 使用空间的尾自减并调用其析构函数. 但是并没有释放内存
    2. void pop_back()
    3. {
    4. --finish;
    5. destroy(finish);
    6. }

    可以看出,push和pop也保证 了finish始终都指向最后一个元素的后一个位置的地址

    删除元素-erase&clear

    void clear() { erase(begin(), end()); }
    
    1. // 清除指定位置的元素. 实际就是将指定位置后面的所有元素向前移动, 最后析构掉最后一个元素
    2. iterator erase(iterator position)
    3. {
    4. if (position + 1 != end())
    5. copy(position + 1, finish, position);
    6. --finish;
    7. destroy(finish);
    8. return position;
    9. }
    10. // 清除一个指定范围的元素, 同样将指定范围后面的所有元素向前移动, 最后析构掉整个范围的元素
    11. // 清除的是左闭右开的区间 [ )
    12. iterator erase(iterator first, iterator last)
    13. {
    14. iterator i = copy(last, finish, first);
    15. destroy(i, finish);
    16. finish = finish - (last - first);
    17. return first;
    18. }

    erase是左闭右开 

    重载运算符

    重载了[] =等运算符之后,用户能更加方便地操作迭代器,看起来就像使用数组一样

    vector之间能相互的复制主要它也重载了=, 使相互传递更加的便利

    1. vector& operator=(const vector& x);
    2. template <class T, class Alloc>
    3. vector& vector::operator=(const vector& x)
    4. {
    5. if (&x != this)
    6. {
    7. // 判断x的数据大小跟赋值的数组大小
    8. if (x.size() > capacity()) // 数组大小过小
    9. {
    10. // 进行范围的复制, 并销毁掉原始的数据.
    11. iterator tmp = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
    12. destroy(start, finish);
    13. deallocate();
    14. // 修改偏移
    15. start = tmp;
    16. end_of_storage = start + (x.end() - x.begin());
    17. }
    18. // 数组的元素大小够大, 直接将赋值的数据内容拷贝到新数组中. 并将后面的元素析构掉
    19. else if (size() >= x.size())
    20. {
    21. iterator i = copy(x.begin(), x.end(), begin());
    22. destroy(i, finish);
    23. }
    24. // 数组的元素大小不够, 装不完x的数据, 但是数组本身的大小够大
    25. else
    26. {
    27. // 先将x的元素填满原数据大小
    28. copy(x.begin(), x.begin() + size(), start);
    29. // 再将x后面的数据全部填充到后面
    30. uninitialized_copy(x.begin() + size(), x.end(), finish);
    31. }
    32. finish = start + x.size();
    33. }
    34. return *this;
    35. }

    容器的调整

    reserver修改容器实际的大小

    1. void reserve(size_type n)
    2. {
    3. // 修改的容器大小要大于原始数组大小才行
    4. if (capacity() < n)
    5. {
    6. const size_type old_size = size();
    7. // 重新拷贝数据, 并将原来的空间释放掉
    8. iterator tmp = allocate_and_copy(n, start, finish);
    9. destroy(start, finish);
    10. deallocate();
    11. // 重新修改3个迭代器位置
    12. start = tmp;
    13. finish = tmp + old_size;
    14. end_of_storage = start + n;
    15. }
    16. }

    resize重新修改数组元素的容量. 这里是修改容纳元素的大小, 不是数组的大小

    1. void resize(size_type new_size) { resize(new_size, T()); }
    2. void resize(size_type new_size, const T& x)
    3. {
    4. // 元素大小大于了要修改的大小, 则释放掉超过的元素
    5. if (new_size < size())
    6. erase(begin() + new_size, end());
    7. // 元素不够, 就从end开始到要求的大小为止都初始化x
    8. else
    9. insert(end(), new_size - size(), x);
    10. }

    swap交换

    1. void swap(vector& x)
    2. {
    3. __STD::swap(start, x.start);
    4. __STD::swap(finish, x.finish);
    5. __STD::swap(end_of_storage, x.end_of_storage);
    6. }

    总结

    本节将vector的删除, 交换, 重载等操作进行的分析. 学到关于交换数组可以修改头尾指针即可, 并不实际交换整个元素. 同时要注意erase清除是一个左闭右开的区间. 因为insert的代码很多,也有一点复杂, 所以我将插入操作放到下节进行分析

  • 相关阅读:
    十年老安卓开发转车载行业,成功斩下50K*13offer的历程经历
    文件IO-缓冲区
    Linux内核源码分析 (B.4) 深度剖析 Linux 伙伴系统的设计与实现
    Python 的切片语法为什么不会出现索引越界呢?
    开发微信公众号本地调试【内网穿透】
    Qt5开发从入门到精通——第十一篇二节(Qt5 事件处理及实例——键盘事件及实例)
    【企业数字化】企业数字化技术应用5大技术趋势
    【Java】PAT Basic Level 1023 组个最小数
    Android多种方法获取系统属性
    动态内存管理+柔性数组+经典笔试题
  • 原文地址:https://blog.csdn.net/weixin_53459056/article/details/126910127