STL vector详解

本文详细解读了STL中的vector容器,介绍了其内存机制、基于_Vector_base的源码分析,以及vector类的关键构造函数、方法和内存操作,如reserve、resize和迭代器功能。
摘要由CSDN通过智能技术生成

1. 简介

本文参考vector源码,主要介绍vector的设计思路,了解一些方法的实现原理,内存机制,和一些实现的方法。

2. vector的内存机制

模板类vector是一种动态数组。在运行阶段可以设置vector对象的长度,可在末尾添加新数据,还可以在中间插入新数据。vector使用new和delete来管理内存,但这种工作是自动完成的,每次内存不够会自动开辟一段新的空间,自动开辟的空间大小是原空间大小的2倍,如果第一次开辟因为原来没有开辟空间就开辟1个字节的空间。其实从内存角度考虑vector就是使用三个指针管理一块内存,这三个指针分别是内存起始位置指针,数据存储终点位置指针,和内存终止位置指针。

3. vector 基类源码_Vector_base

源码如下:

template <class _Tp, class _Alloc> 
class _Vector_base {
public:
  typedef _Alloc allocator_type;
  allocator_type get_allocator() const { return allocator_type(); }

  _Vector_base(const _Alloc&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) {}
  _Vector_base(size_t __n, const _Alloc&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) 
  {
    _M_start = _M_allocate(__n);
    _M_finish = _M_start;
    _M_end_of_storage = _M_start + __n;
  }

  ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }

protected:
  _Tp* _M_start;
  _Tp* _M_finish;
  _Tp* _M_end_of_storage;

  typedef simple_alloc<_Tp, _Alloc> _M_data_allocator;
  _Tp* _M_allocate(size_t __n)
    { return _M_data_allocator::allocate(__n); }
  void _M_deallocate(_Tp* __p, size_t __n) 
    { _M_data_allocator::deallocate(__p, __n); }
};

3.1. vector 基类成员变量

  _Tp* _M_start;  //vector存储数据存储的首地址
  _Tp* _M_finish; //vector存储数据存储的尾地址+1 其实就是vector::end()返回的迭代器
  _Tp* _M_end_of_storage; //vector占用内存的尾地址

其实vector中只有三个指针成员因此sizeof一个vector对象的大小就是sizeof指针大小的三倍,32bit系统和64bit系统可能会有一些差别。64bit系统中vector占用内存空间为3*8=24字节。

3.2. vector 基类方法

构造函数

  _Vector_base(const _Alloc&)  // 指定一个空间配置器
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) {}
  _Vector_base(size_t __n, const _Alloc&)  //指定vector 空间大小__n*sizeof(_Tp) 指定一个空间配置器
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) 
  {
    _M_start = _M_allocate(__n); //这行代码相当于开辟了n*sizeof(_Tp) (_Tp是vector中存储类型)这么大的空间
    _M_finish = _M_start; //没有成员时finish = start
    _M_end_of_storage = _M_start + __n; //vector占用内存的尾地址
  }
  allocator_type get_allocator() const { return allocator_type(); } //获取空间配置器类型
 _Tp* _M_allocate(size_t __n);  //开辟空间
 void _M_deallocate(_Tp* __p, size_t __n);  //释放空间

3.3. _Vector_base 总结

通过两个构造函数就可以知道,构造_Vector_base 时需要指定空间配置器同时也可以指定size,如果指定了size就会开辟sizesizeof(_Tp)这么大的空间,_M_start 指针指向这块空间的首地址,_M_finish 和_M_start 指向同一块地址(因为目前虽然开辟了空间但是并没有向vector中存入数据)。_M_start 指向的是vector中存入数据的首地址,_M_finish指向的是vector中存入数据的尾地址+1(其实就是vector::end()返回的迭代器),_M_end_of_storage就是vector内开辟空间的尾地址+1,也就是(vector::capacity()返回的值)
下图为_M_start ,_M_finish ,_M_end_of_storage指针在vector中所指向的内存位置示意图使用的是vector<int32_t>
下图vector中开辟了4
4个字节的空间(相当于调用vector<int32_t>::reserve(4)),并且向vector中插入了2个int32_t值1,2。
在这里插入图片描述

4. vector类

其实vector源码中_Vector_base 类的源码就可以展示出vector的设计思路也是精华部分,vector类中的方法主要提供给用户使用vector,因此vector那部分源码就不展示了感兴趣的可以自己去看看。
vector类中没有任何成员,继承了_Vector_base 类提供了一些公有的方法,下面主要说明下vector中的公有方法

4.1. 方法

首先了解下vector中typedef的部分类型

  typedef _Tp value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type* iterator;   //迭代器其实就是指针
  typedef const value_type* const_iterator;
  typedef value_type& reference;  //引用
  typedef const value_type& const_reference;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;

vector的构造函数

  explicit vector(const allocator_type& __a = allocator_type())     //可以指定空间配置器,也可以使用默认的空间配置器
    : _Base(__a) {}

  vector(size_type __n, const _Tp& __value,
         const allocator_type& __a = allocator_type())     //可以指定vector成员个数和初始化成员的值
    : _Base(__n, __a)
    { _M_finish = uninitialized_fill_n(_M_start, __n, __value); }

  explicit vector(size_type __n)    //可以指定vector成员个数,指定个数同时就会开辟对应的空间sizeof(_Tp)*__n
    : _Base(__n, allocator_type())
    { _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); }

  vector(const vector<_Tp, _Alloc>& __x)  //拷贝构造
    : _Base(__x.size(), __x.get_allocator())
    { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }
  vector(const _Tp* __first, const _Tp* __last,
         const allocator_type& __a = allocator_type())  //从迭代器的__first位置拷贝到迭代器__last位置
    : _Base(__last - __first, __a)   //相当于在基类里面创建了一个__last - __first这么大的空间
    { _M_finish = uninitialized_copy(__first, __last, _M_start); }
函数描述
iterator begin()获取_M_start位置的迭代器也就是vector开辟内存的起始指针有个重载返回的是const 的_M_start位置的迭代器
const_iterator cbegin()返回的是一个const 的_M_start位置的迭代器
iterator end()获取_M_finish位置的迭代器也就是vector内尾成员后一个位置的指针,有个重载返回的是const 的_M_finish位置的迭代器
const_iterator cend()返回的是一个const 的_M_finish位置的迭代器
reverse_iterator rbegin()返回的是一个reverse_iterator内部存储_M_finish位置的迭代器,但是里面实现很多重载操作符比如operator*()实际返回的是_M_finish位置前一个位置的内容返回值类似 * - - _M_finish
const_reverse_iterator crbegin()返回const_reverse_iterator
reverse_iterator rend()返回的是一个reverse_iterator内部存储_M_start位置的迭代器,但是里面实现很多重载操作符比如operator*()实际返回的是_M_start位置前一个位置的内容返回值类似 * - - _M_start
const_reverse_iterator crend()返回const_reverse_iterator
size_type size()返回的是_M_finish-_M_start也就是vector中实际存储的成员个数
size_type max_size()返回vector所能储存的最大的元素数目,容器所能容纳的最大元素数目,这是系统或者库所实施的限制。但是容器不一定保证能达到该大小,有可能在还未达到该大小的时候,就已经无法继续分配任何的空间了。
size_type capacity()返回容器的容量(开辟空间大小/sizeof(_Tp))比如vector<int32_t>如果返回的是10也就代表当前容量最多可以存储10个uint32_t也就是开辟了4*10这么大空间
bool empty()返回的是begin()==end() 也就是容器是否是空
reference operator[](size_type __n)返回的是一个*(begin()+__n)引用 还有个重载返回的是一个const 引用
void reserve(size_type __n)()设置vector容量为__n及如果当前容量小于__n则需要开辟到__n*sizeof(_Tp)(这么大就可以存储__n个_Tp类型的对象),如果当前容量大于__n则直接返回
void assign(size_type __n, const _Tp& __val)给vector填充__n个 值为__val 的数据
template < class _InputIterator>
void assign(_InputIterator __first, _InputIterator __last)
给vector重新填充数据从迭代器__first到迭代器__last,set的begin(),end()填入该函数可以将set的值赋值给vector
reference front()返回一个*begin()也就是返回vector中起始位置的引用
const_reference front()返回一个*begin()也就是返回vector中起始位置的const 引用
reference back()返回一个*(end()-1)也就是返回vector中末尾位置的引用
const_reference back()返回一个*(end()-1)也就是返回vector中末尾位置的const 引用
void push_back(const _Tp& __x)在vector末尾插入一个值,现在可以使用emplace_back代替,emplace_back效率更高少一次拷贝
void emplace_back(_Args&&… __args)在vector末尾插入一个值
template< typename _InputIterator>
void insert(iterator __position, _InputIterator __first, _InputIterator __last)
在指定位置插入从__first到__last之间的所有值并返回__first插入位置的迭代器
iterator insert(const_iterator __position, size_type __n, const value_type& __x)在指定位置插入n个值为__x的值并返回第一个插入位置的迭代器
iterator insert(const_iterator __position, initializer_list<value_type> __l)在指定位置插入一个C风格的数组并返回第一个插入位置的迭代器
iterator insert(const_iterator __position, const value_type& __x)在指定位置插入该值并返回该位置的迭代器
iterator emplace(const_iterator __pos, _Args&&… __args)在指定位置插入该值并返回该位置的迭代器
iterator erase(iterator __position)删除指定位置的值,返回的迭代器指向删除的值的下一个位置
void swap(vector& __x)当前vector和参数中的vector里面的值进行交换
void clear()清空vector
  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值