本节分析vector是如何进行插入操作的,以及数组大小不足后,insert怎么来处理
insert()为了接受不同参数,定义了多个重载函数~~~
insert_aux函数执行插入操作- iterator insert(iterator position) { return insert(position, T()); }
- iterator insert(iterator position, const T& x) ;
-
- iterator insert(iterator position, const T& x)
- {
- size_type n = position - begin();
- // 如果数组还有备用空间, 并且插入的是finish位置, 直接插入即可, 最后调整finish就行了.
- if (finish != end_of_storage && position == end())
- {
- construct(finish, x);
- ++finish;
- }
- // 以上条件不成立, 调用另一个函数执行插入操作
- else
- insert_aux(position, x);
- return begin() + n;
- }
insert_aux:
- void insert_aux(iterator position, const T& x);
-
- template <class T, class Alloc>
- void vector
::insert_aux(iterator position, const T& x) - {
- // 如果数组还有备用空间, 就直接移动元素, 再将元素插入过去, 最后调整finish就行了.
- if (finish != end_of_storage)
- {
- // 调用构造, 并将最后一个元素复制过去, 调整finish
- construct(finish, *(finish - 1));
- ++finish;
- T x_copy = x;
- // 将插入元素位置的后面所有元素往后移动, 最后元素插入到位置上.
- copy_backward(position, finish - 2, finish - 1);
- *position = x_copy;
- }
- // 没有备用空间, 重新申请空间再将元素拷贝过去同时执行插入操作
- else {
- const size_type old_size = size();
- const size_type len = old_size != 0 ? 2 * old_size : 1; // 重新申请空间原始空间的两倍+1的空间
-
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY {
- // 进行分段将原始元素拷贝新的空间中, 这样也就实现了插入操作
- new_finish = uninitialized_copy(start, position, new_start);
- construct(new_finish, x);
- ++new_finish;
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
-
- # ifdef __STL_USE_EXCEPTIONS
- catch(...) {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- // 释放掉原来的空间, 调整新的3个迭代器的位置
- destroy(begin(), end());
- deallocate();
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
- void insert (iterator pos, size_type n, const T& x);
- void insert (iterator pos, int n, const T& x)
- {
- insert(pos, (size_type) n, x);
- }
- void insert (iterator pos, long n, const T& x)
- {
- insert(pos, (size_type) n, x);
- }
如果备用空间足够大, 先保存插入位置到end的距离
1.从插入的位置到end的距离大于要插入的个数n
2.从插入的位置到end的距离小于要插入的个数
备用空间不足的时候执行
- template <class T, class Alloc>
- void vector
::insert(iterator position, size_type n, const T& x) - {
- if (n != 0)
- {
- // ******** 1 ***********
- // 备用空间足够大
- if (size_type(end_of_storage - finish) >= n)
- {
- T x_copy = x;
- // 保存插入位置到end的距离
- const size_type elems_after = finish - position;
- iterator old_finish = finish;
- // ******* a **********
- // 从插入的位置到数据结束的距离大于了要插入的个数n
- if (elems_after > n)
- {
- // 先构造出finish-n个大小的空间, 再移动finish - n个元素的数据
- uninitialized_copy(finish - n, finish, finish);
- finish += n;
- // 在将从插入位置后的n个元素移动
- copy_backward(position, old_finish - n, old_finish);
- // 元素从插入位置开始进行填充即可
- fill(position, position + n, x_copy);
- }
- // ********* b *********
- // 从插入的位置到end的距离小于了要插入的个数
- else
- {
- // 先构造出n - elems_after个大小的空间, 再从finish位置初始化n - elems_after为x
- uninitialized_fill_n(finish, n - elems_after, x_copy);
- finish += n - elems_after;
- // 从插入位置开始到原来的finish位置结束全部复制到新的结束位置后面
- uninitialized_copy(position, old_finish, finish);
- finish += elems_after;
- // 从插入位置进行填充x
- fill(position, old_finish, x_copy);
- }
- }
- // ******* 2 ***********
- // 空间不足处理
- else
- {
- // 重新申请一个当前两倍的空间或者当前大小+插入的空间, 选择两者最大的方案.
- const size_type old_size = size();
- const size_type len = old_size + max(old_size, n);
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY
- {
- // 同样进行分段复制到新的数组中, 从而实现插入
- new_finish = uninitialized_copy(start, position, new_start);
- new_finish = uninitialized_fill_n(new_finish, n, x);
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
- # ifdef __STL_USE_EXCEPTIONS
- catch(...)
- {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- // 将当前数组的元素进行析构, 最后释放空间
- destroy(start, finish);
- deallocate();
- // 修改3个迭代器
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
- }
- template <class T, class Alloc>
- void vector
::insert(iterator position, const_iterator first, const_iterator last) { - // 插入不为空
- if (first != last) {
- size_type n = 0;
- // 计算插入的长度, 并保存在n中
- distance(first, last, n);
- // 如果是剩余的空间大于插入的长度.
- if (size_type(end_of_storage - finish) >= n) {
- // 保存插入点到end的距离
- const size_type elems_after = finish - position;
- iterator old_finish = finish;
- // 同样比较n与插入点到end的距离, 下面的过程与上面描述的基本一致.
- // 从插入的位置到end的距离大于要插入的个数n
- if (elems_after > n) {
- uninitialized_copy(finish - n, finish, finish);
- finish += n;
- copy_backward(position, old_finish - n, old_finish);
- copy(first, last, position);
- }
- else {
- uninitialized_copy(first + elems_after, last, finish);
- finish += n - elems_after;
- uninitialized_copy(position, old_finish, finish);
- finish += elems_after;
- copy(first, first + elems_after, position);
- }
- }
- else {
- const size_type old_size = size();
- const size_type len = old_size + max(old_size, n);
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY {
- new_finish = uninitialized_copy(start, position, new_start);
- new_finish = uninitialized_copy(first, last, new_finish);
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
- # ifdef __STL_USE_EXCEPTIONS
- catch(...) {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- destroy(start, finish);
- deallocate();
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
- }
vector适合用来做随机访问很快, 也支持适合频率较低的插入和删除操作, 在每次插入和删除后迭代器都会失效, 因为不能保证操作之后迭代器的位置没有改变