【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) 均会导致未定义行为。
相关推荐
会员源码网2 天前
尝试修改常量值(`Fatal error: Cannot re-assign auto-global variable _POST`)
编程语言·代码规范
怕浪猫2 天前
第21章:微服务与分布式架构中的Go应用
后端·go·编程语言
怕浪猫4 天前
第20章:Web服务实战——构建RESTful API
后端·go·编程语言
Arjun7 天前
C语言基础内容整理
编程语言
怕浪猫7 天前
第19章:Go语言工具链与工程实践
后端·go·编程语言
番茄灭世神8 天前
Rust学习笔记第2篇
rust·编程语言
怕浪猫8 天前
第18章:测试与性能调优——unit test与benchmark
后端·google·编程语言
怕浪猫9 天前
第17章:反射与泛型编程——运行时能力与代码复用
后端·go·编程语言
长安牧笛11 天前
让车学会耍赖式安全停车,危险时优先靠边停车,不是硬刹,颠覆紧急制动逻辑,输出平稳停车。
python·编程语言