vector容器的动态分配空间

vector容器的底层实现基于数组,里面封装了大量高效的方法,可以完美取代掉数组。整个容器的核心实际上就是动态分配内存,也是其性能优于数组的重要原因。下面重点解析它的核心函数push_back函数:

当数组中增加一个元素x的时候,先判断是否还有备用空间;如果还有备用空间,则将当前指针的值设为x,并将当前的指针加1;若备用空间已经用完,如果之前的空间为0,则重新分配大小为1的空间,否则将空间扩容为之前的两倍,然后将旧容器中的值重新拷贝到新空间中,并重新分配起始指针和当前指针。所以使用vector需要注意的一点就是尽量不要动态给它分配空间。而且空间重新分配之后,之前的所有指针都会失效(特别要注意)

vector扩容机制取决于编译器类型:VS2015-----1.5倍扩容;g++编译器-------2倍扩容

具体实现:

void push_back(const T& x) {
    if (finish != end_of_storage) { //若当前还有备用空间
      construct(finish, x); //将当前水位的值设为x
      ++finish; //提升水位
    }
    else
      insert_aux(end(), x); 
}
template <class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x) {
  if (finish != end_of_storage) {
    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; //将当前数组的容量扩大为原来的两倍
    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); //将当前数组的水位的值设为x
      ++new_finish; //提升新数组的水位
      new_finish = uninitialized_copy(position, finish, new_finish); //这语句感觉可有可无,因为它根本就不会执行,position即last,而finish也是last
    }

#       ifdef  __STL_USE_EXCEPTIONS 
    catch(...) { //如果重新构造的新数组出现异常,则销毁当前新创建的数组,并释放内存空间
      destroy(new_start, new_finish); 
      data_allocator::deallocate(new_start, len);
      throw;
    }
#       endif /* __STL_USE_EXCEPTIONS */
    destroy(begin(), end()); //将旧数组的空间释放掉
    deallocate();
    start = new_start; //new_start记录新数组的起始位置
    finish = new_finish; //重新设置当前水位的指针
    end_of_storage = new_start + len; //设置新数组的容量
  }
}

[1]《STL源码分析》----侯捷

[2]《STL3.0源码》

### C++ `vector` 容器作为动态数组的使用方法 #### 导入头文件 为了使用 `vector` 动态数组容器,程序中需要导入 `<vector>` 头文件[^1]。 ```cpp #include <iostream> #include <vector> using namespace std; ``` #### 创建 `vector` 对象 创建一个 `vector<int>` 类型的对象来存储整数类型的元素。可以通过多种方式初始化: - 默认构造函数创建空向量: ```cpp vector<int> vec; ``` - 初始化列表指定初始元素: ```cpp vector<int> vec = {1, 2, 3}; ``` - 使用迭代器范围构造函数从现有数组复制数据[^3]: ```cpp int arr[] = {1, 2, 5, 6, 7}; vector<int> vec(begin(arr), end(arr)); ``` #### 添加和访问元素 通过成员函数如 `push_back()` 向末尾添加新元素,并利用下标运算符 `[index]` 或者 `at(index)` 方法获取特定位置上的值。 ```cpp vec.push_back(8); // 添加新的元素到末尾 cout << vec[0]; // 访问第一个元素 cout << vec.at(4); // 访问第五个元素(安全检查) ``` #### 查询大小信息 可以调用 `size()` 获取当前已存元素数量,而 `capacity()` 返回分配的空间大小,即使这些空间尚未被占用[^4]。 ```cpp cout << "Size: " << vec.size(); // 当前使用的元素数目 cout << "Capacity: " << vec.capacity();// 已分配但可能未完全使用的总容量 ``` #### 修改容量 当预计未来会增加更多项时可提前预留空间以提高性能效率;同样也可以让实际使用的内存更贴近需求减少浪费。 ```cpp vec.reserve(100); // 提前申请至少能容纳100个元素的空间 if (!vec.empty()) { vec.shrink_to_fit(); // 尽量释放多余不用的内部缓冲区 } ``` #### 删除操作 移除最后一个元素或清空整个集合都很容易实现。 ```cpp if (!vec.empty()) { vec.pop_back(); // 移除最后面的一项 } vec.clear(); // 清理所有项目使长度变为零 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值