C++ STL : vector

1概述

c++提供了array, STL再提供vector、list、deque、stack、queue、priority_queue

vector和array区别

array是静态的空间,不能原地扩充, 一旦配置好了就不能变了,要是不够了,就得我们自己弄,再新建一个、复制、释放,好麻烦的

vector就是STL全包了,不用我们动手了

两倍扩充, 找不到两倍就结束了

#include<vectoe> -> #include<stl_vector.h>

2 迭代器

空间连续 类普通指针 RAI

连续的不用太复杂, 指针就可以了

3 数据结构

start、finish、end_of_storage

容器是前闭后开, finish指向超尾

连续空间支持[]

```C++
struct _Vector_impl
  : public _Tp_alloc_type
  {
pointer _M_start;
pointer _M_finish;
pointer _M_end_of_storage;
```

size() capacity()

新增元素时,一般扩充两倍, 不同编译器不同

扩充: 重新申请、复制、释放

4 构造和内存管理

```C++
vector(size_type __n, const value_type& __value,
     const allocator_type& __a = allocator_type())
  : _Base(__n, __a)
  { _M_fill_initialize(__n, __value); }

void
  _M_fill_initialize(size_type __n, const value_type& __value) // fill_initialize(n, value);
  {
this->_M_impl._M_finish = std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value,
				_M_get_Tp_allocator());
  }//我看源码就是一直调用函数,最终调用的是construct
```

5 vector操作 push_back、pop_back、emplace_back、erase、clear、insert

5.1 push_back()

```C++
void
  push_back(const value_type& __x)
  {
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) //finish != end_of_storage
  {
    _GLIBCXX_ASAN_ANNOTATE_GROW(1);
    _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
			     __x);  //在finish处构造
    ++this->_M_impl._M_finish;//finish++
    _GLIBCXX_ASAN_ANNOTATE_GREW(1);
  }
else
  _M_realloc_insert(end(), __x);    //没有空间了
  }
```

```C++
template<typename _Tp, typename _Alloc>
void
vector<_Tp, _Alloc>::
_M_realloc_insert(iterator __position, const _Tp& __x) //end(), x
#endif
    {
    const size_type __len =
    _M_check_len(size_type(1), "vector::_M_realloc_insert");//配置新大小
    pointer __old_start = this->_M_impl._M_start;
    pointer __old_finish = this->_M_impl._M_finish;//保存就指针
    const size_type __elems_before = __position - begin();
    pointer __new_start(this->_M_allocate(__len));//重新构造
    pointer __new_finish(__new_start);
    __try//复制原有元素
    {
    // The order of the three operations is dictated by the C++11
    // case, where the moves could alter a new element belonging
    // to the existing vector.  This is an issue only for callers
    // taking the element by lvalue ref (see last bullet of C++11
    // [res.on.arguments]).
    _Alloc_traits::construct(this->_M_impl,
                __new_start + __elems_before,
#if __cplusplus >= 201103L
                std::forward<_Args>(__args)...);
#else
                __x);
#endif
    __new_finish = pointer();

    __new_finish
        = std::__uninitialized_move_if_noexcept_a
        (__old_start, __position.base(),
        __new_start, _M_get_Tp_allocator());

    ++__new_finish;

    __new_finish
        = std::__uninitialized_move_if_noexcept_a
        (__position.base(), __old_finish,
        __new_finish, _M_get_Tp_allocator());
    }
    __catch(...)
    {
    if (!__new_finish)
        _Alloc_traits::destroy(this->_M_impl,
                __new_start + __elems_before);
    else
        std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
    _M_deallocate(__new_start, __len);
    __throw_exception_again;
    }
    _GLIBCXX_ASAN_ANNOTATE_REINIT;
    std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());//析构原vector
    _M_deallocate(__old_start,
            this->_M_impl._M_end_of_storage - __old_start);//释放内存
    this->_M_impl._M_start = __new_start;
    this->_M_impl._M_finish = __new_finish;
    this->_M_impl._M_end_of_storage = __new_start + __len;
    }
```

空间重新配置后,原来的迭代器都失效了

5.2 pop_back()

```C++
void
  pop_back() _GLIBCXX_NOEXCEPT
  {
__glibcxx_requires_nonempty();
--this->_M_impl._M_finish;  //--finish
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); //析构超尾元素
_GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
  }
```

5.3 erase()

```C++
erase(iterator __first, iterator __last)
  { return _M_erase(__first, __last); 

template<typename _Alloc>
typename vector<bool, _Alloc>::iterator
vector<bool, _Alloc>::
_M_erase(iterator __first, iterator __last)
{
  if (__first != __last)
_M_erase_at_end(std::copy(__last, end(), __first)); //复制last到finish到一个新的空间里并返回到__first上
  return __first;
}
```

5.4 insert()

代码很长,我就不放了, 见侯老师的书或者看源码也行
因为是立着画的, 所以画的不太好

还有个问题,我觉得第一个old_finish和finish一样的话两次复制不就覆盖掉了吗? 没明白

  • 第一种情况: 备用空间够用且插入位置后面的元素大于插入元素
    在这里插入图片描述

  • 第二种情况: 备用空间够用且插入位置后面的元素小于插入元素
    在这里插入图片描述

  • 第三种情况: 备用空间不够用
    在这里插入图片描述

侯老师视频补充知识点

未指定空间大小为0

move()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值