【C++STL】Vector的使用(1)

基本用法

  • vector 定义在 <vector> 头文件中,需包含后使用
c++ 复制代码
#include <vector>
  • 初始化
c++ 复制代码
// 1、空构造函数,构造一个空的vector
vector<int> v1;
cout << v1.size() << "  " << v1.capacity() << endl;

// 2、指定大小,默认初始化(int默认0,string默认空)
vector<int> v2(10);
cout << v2.size() << "  " << v2.capacity() << v2.at(0) <<  endl;

// 指定大小、指定初始化值
vector<int> v3(10, 5);
cout << v3.size() << "  " << v3.capacity() << v3.at(0) << endl;

// 3、拷贝构造,从其他对象构造一个
vector<int> v4(v3);
cout << v4.size() << "  " << v4.capacity() << v4.at(0) << endl;

// 4、列表初始化
vector<int> v5 = { 0, 1, 2, 3, 4, 5 };
cout << v5.size() << "  " << v5.capacity() << v5.at(2) << endl;

// 5、迭代器范围初始化
vector<int> v6(v5.begin() + 1, v5.end() - 1 );
cout << v6.size() << "  " << v6.capacity() << v6.at(2) << endl;
  • 元素访问
    • 下标访问[](无越界检查)
c++ 复制代码
vector<int> vt = { 1, 2, 3, 4, 5 };

// 1、下标访问
cout << vt[1] << endl;

// 越界访问,程序中断
cout << vt[10] << endl;
  • at()访问(有越界检查,抛异常out_of_range)
c++ 复制代码
vector<int> vt = { 1, 2, 3, 4, 5 };

// 2、at()访问
cout << vt.at(2) << endl;

// 越界访问,抛出异常
cout << vt.at(10) << endl;
  • front() / back() 访问首尾元素
c++ 复制代码
vector<int> vt = { 1, 2, 3, 4, 5 };

// 3、访问首尾元素
cout << vt.front() << " " << vt.back() << endl;
  • 迭代器访问(遍历专用)
c++ 复制代码
vector<int> vt = { 1, 2, 3, 4, 5 };

// 4、迭代器访问
for (vector<int>::iterator begin = vt.begin(); begin < vt.end(); ++begin)
{
	cout << *begin << endl;
}

核心操作方法

增删元素

  • 尾部增删(推荐,效率高)
    • push_back(val)尾部添加元素
    • emplace_back(val):C++11 新增,直接在尾部构造元素(避免拷贝,效率更高);
    • pop_back():删除尾部元素(无返回值)。
c++ 复制代码
vector<int> vt;

// 尾部添加元素
vt.push_back(1);

// 尾部构造
vt.emplace_back(2);

// 尾部删除
vt.pop_back()
  • 指定位置增删
    • insert(pos, val):在迭代器 pos 处插入元素,返回新元素的迭代器;
    • emplace(pos, val):C++11 新增,在 pos 处构造元素;
    • erase(pos):删除 pos 处的元素,返回下一个有效迭代器;
    • erase(begin, end):删除区间内的元素。
c++ 复制代码
vector<int> vt = {1, 3 ,5};

// 1、insert插入元素
vector<int>::iterator begin = vt.begin();
vt.insert(begin + 1, 2);

// 2、emplace在指定pos出构造元素
begin = vt.begin();
vt.emplace(begin + 3, 4);

// 3、删除指定位置的元素,返回下一个有效迭代器
// end迭代器返回的是末尾元素的下一位置迭代器,因此-1
vector<int>::iterator rs = vt.erase(vt.end()-1);
//cout << *rs << endl;


// 4、删除区间
vt.erase(vt.begin(), vt.begin() + 2);


for (vector<int>::iterator begin = vt.begin(); begin != vt.end(); ++begin)
{
	cout << *begin << endl;
}
  • 清空与重置
    • clear():清空所有元素(size 变为 0,capacity 不变);
    • resize(n):调整 size 为 n,不足补默认值,超出则截断;
    • assign(n, val):清空原有元素,重新赋值 n 个 val;
    • swap(v2):与另一个 vector 交换数据(O (1) 效率)。
c++ 复制代码
vector<int> vt = {1, 3 ,5};

vt.clear();

容量与大小管理

size()返回当前元素个数(实际存储的元素数) capacity()返回当前分配的内存可容纳的元素数(不含额外空间) empty()判断是否为空(size==0 时返回 true) reserve(n)预分配至少 n 个元素的内存(仅扩容 capacity,不改变 size)

vector性能优化

  1. 减少扩容次数,扩容会触发"分配新内存-拷贝元素-释放原内存"的过程,耗费时间且会导致迭代器失效问题。优化方法:提前使用reserve预分配足够的内存。
  2. 使用emplace_back替代push_back,push_back 会先构造临时对象,再拷贝到容器;emplace_back 直接在容器内存中构造对象,减少拷贝:
  3. 批量操作替代单次操作,如在插入和删除多个元素时,优先使用区间操作。

避坑点

  1. 迭代器失效
    1. 扩容后,所有的迭代器、指针、引用失效
    2. 插入元素,插入位置后的迭代器失效
    3. 删除元素,删除位置后的迭代器失效 避坑方法:修改容器后,重新获取迭代器。
  2. size和capacity要分清,size是实际元素个数,capacity是已分配内存可容纳的元素个数;
  3. 空vector的访问,空 vector 的 begin() == end(),front()/back()/at(0) 均会导致未定义行为。
相关推荐
潍坊老登14 小时前
90%的软件项目卡在第一步:需求“想得美、写不清”
编程语言
iiiiyu15 小时前
面向对象高级接口的综合案例
java·开发语言·数据结构·编程语言
Rust研习社20 小时前
Rust 是如何判断对象是否相等的?一起来聊一聊 PartialEq 与 Eq
后端·rust·编程语言
7年前端辞职转AI2 天前
Python 错误和异常处理
python·编程语言
7年前端辞职转AI2 天前
Python 面向对象编程
python·编程语言
7年前端辞职转AI3 天前
Python 文件操作
python·编程语言
7年前端辞职转AI3 天前
Python 容器数据类型
python·编程语言
7年前端辞职转AI3 天前
Python 流程控制语句
python·编程语言
7年前端辞职转AI3 天前
Python 运算符
python·编程语言
7年前端辞职转AI3 天前
Python 变量
python·编程语言