【C++】标准模板库(STL)—— vector容器快速上手算法必看!!!

Vector 容器基础知识详解

一、Vector 容器概述

1. 基本定义

  • 动态数组:STL中最常用的序列容器
  • 内存连续:元素存储在连续内存空间
  • 自动扩容:插入元素超出容量时自动扩展内存(通常2倍扩容)

2. 核心特性对比

特性Vector原生数组
内存管理✅ 自动扩容/缩容❌ 固定大小
随机访问⚡️ O(1)⚡️ O(1)
尾部操作⚡️ O(1) 高效N/A
头部操作⚠️ O(n) 低效N/A
迭代器安全⚠️ 插入/删除失效✅ 稳定
线程安全❌ 需外部同步❌ 非线程安全

二、vector的构造方法

带参数构造函数

C++ 中的 vector 容器提供了多种构造方式,以下是三种主要的带参数构造方法:

  1. 区间构造
    vector(beg, end);
    [beg, end) 区间内的元素拷贝给容器(左闭右开)。

  2. 填充构造
    vector(n, elem);
    构造包含 n 个相同元素 elem 的容器。

  3. 拷贝构造
    vector(const vector &vec);
    拷贝构造函数,复制另一个 vector 容器的所有元素。


基本声明语法

// 基础声明格式
vector<T> vecT;

// 示例声明
vector<int> vecInt;         // 存放 int 类型
vector<float> vecFloat;     // 存放 float 类型
vector<string> vecString;   // 存放 string 类型

// 自定义类型
class CA {};
vector<CA*> vecpCA;         // 存放指针
vector<CA> vecCA;           // 存放对象

示例代码

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	int iArray[] = { 0,1,2,3,4 };

	// 1. 数组区间构造
	vector<int> vecIntA(iArray, iArray + 5);  // 拷贝整个数组(左闭右开)

	// 2. 迭代器区间构造
	vector<int> vecIntB(vecIntA.begin(), vecIntA.end());  // 拷贝整个vector
	//vector<int> vecIntB(vecIntA.begin(), vecIntA.begin() + 3);  // 只拷贝前3个元素

	// 3. n个elem构造
	vector<int> vecIntC(3, 9);  // 构造包含3个9的vector
	for (int i = 0;i < 3;i++) {
		cout << vecIntC[i] << " " ;
	}
	cout << endl;

	// 4. 拷贝构造
	vector<int> vecIntD(vecIntA);  // 拷贝整个vecIntA
	for (int i = 0;i < 5;i++) {
		cout << vecIntD[i] << " ";
	}
	cout << endl;

	return 0;
}

三、vector的赋值

示例代码

#include<iostream>
#include<vector>
using namespace std;

// 辅助函数:打印 vector 内容
void printVector(const vector<int>& vec, const string& name) {
	cout << name << ": [ ";
	for (int num : vec) {
		cout << num << " ";
	}
	cout << "]" << endl;
}

int main()
{
    vector<int> vecIntA, vecIntB, vecIntC, vecIntD;
    int iArray[] = { 0, 1, 2, 3, 4 };

    // 操作1: 用数组初始化 vecIntA
    vecIntA.assign(iArray, iArray + 5);  // 用其它容器的迭代器作参数
    printVector(vecIntA, "操作1后的vecIntA");  // 输出: [ 0 1 2 3 4 ]

    // 操作2: 用 vecIntA 初始化 vecIntB
    vecIntB.assign(vecIntA.begin(), vecIntA.end());
    printVector(vecIntB, "操作2后的vecIntB");  // 输出: [ 0 1 2 3 4 ]

    vecIntB.assign(vecIntA.begin()+2, vecIntA.end()-1);
    printVector(vecIntB, "操作2后的vecIntB");  // 输出: [ 2 3 ]

    // 操作3: 直接初始化 vecIntC
    vecIntC.assign(3, 9);
    printVector(vecIntC, "操作3后的vecIntC");  // 输出: [ 9 9 9 ]

    // 操作4: 用 operator= 赋值
    vecIntD = vecIntA;
    printVector(vecIntD, "操作4后的vecIntD");  // 输出: [ 0 1 2 3 4 ]

    // 操作5: 交换 vecIntA 和 vecIntD
    vecIntA.swap(vecIntB);
    printVector(vecIntA, "操作5后的vecIntA");  // 输出: [ 2 3 ] 
    printVector(vecIntB, "操作5后的vecIntD");  // 输出: [ 0 1 2 3 4 ]

    // 注意:因交换前内容相同,结果不变

	return 0;
}

四、vector的大小

1. 获取容器中元素数量

vector.size();

返回容器中元素的个数

2. 检查容器是否为空

vector.empty();

判断容器是否为空

3. 调整容器大小(默认填充)

vector.resize(num);

重新指定容器的长度为num
若容器变长,则以默认值填充新位置
若容器变短,则末尾超出容器长度的元素被删除

4. 调整容器大小(指定填充值)

vector.resize(num, elem);

重新指定容器的长度为num
若容器变长,则以elem值填充新位置
若容器变短,则末尾超出容器长度的元素被删除


示例代码

#include<iostream>
#include<vector>
using namespace std;

int main()
{
    vector<int> v1;
    cout << "v1.size" << v1.size() << endl;
    if (v1.empty())
    {
        cout << "v1 is empty" << endl;
    }

    int iArray[] = { 0,1,2,3,4 };
    v1.assign(iArray, iArray + 5);
    cout << "赋值后:";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;

    // 将容器的长度变长
    v1.resize(10); 

    cout << "变长后(默认填充): ";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;

    // 将容器的长度变短
    v1.resize(3);  

    cout << "变短后: ";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;

    // 将容器的长度变长,并且扩展出来的新元素赋值为指定的值!
    v1.resize(10, 100);  

    cout << "变长后(指定填充值100): ";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;

    return 0;
}

五、vector元素的访问方式

示例代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int a[] = { 1,2,3,4 };
    vector<int> v1(a, a + 4);
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;
    // v1[8] = 100; // 危险的下标越界访问
    // v1.at(8) = 100; // 会抛出std::out_of_range异常

    return 0;
}

六、vector插入函数insert的使用

1. 在pos位置插入一个elem元素的拷贝, 返回新数据的位置
vector.insert(pos,elem);

2. 在pos位置插入n个elem数据, 无返回值
vector.insert(pos,n,elem);

3. 在pos位置插入[beg,end)区间的数据, 无返回值
vector.insert(pos,beg,end);


示例代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int a[] = { 1,2,3,4 };
    vector<int> v1(a, a + 4);
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;

    // 使用已有的v1容器(不再重新声明)
    v1.clear();  // 清空原有内容,准备重新添加元素

    // 尾部添加元素
    v1.push_back(1);  // 在容器尾部加入一个元素
    v1.push_back(3);
    v1.push_back(5);
    v1.push_back(7);
    v1.push_back(9);

    // 尾部移除元素
    v1.pop_back();   // 删除最后一个元素 (9)
    v1.pop_back();   // 删除最后一个元素 (7)

    // 验证结果
    cout << "当前元素:";
    for (int num : v1) {
        cout << num << " ";
    }
    cout << endl; // 输出:1 3 5
    
    // 在指定位置插入单个元素
    v1.insert(v1.begin() + 3, 100); // 注意:第一个参数为迭代器位置
    cout << "插入单个元素后:";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;
    // 此时v1内容: 1 3 5 100

    // 在指定位置插入多个相同元素
    v1.insert(v1.begin() + 3, 3, 1000); // 在下标3位置插入3个1000
    cout << "插入多个相同元素后:";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;
    // 此时v1内容: 1 3 5 1000 1000 1000 100

    // 在指定位置插入区间元素
    int b[] = { 40, 50, 60, 70, 80, 90 };
    // 将b数组中索引[1,5)区间的元素插入到v1位置7
    v1.insert(v1.begin() + 7, b + 1, b + 5);
    cout << "插入区间元素后:";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;
    // 此时v1内容: 1 3 5 1000 1000 1000 100 50 60 70 80

    vector<int> v2(b, b + 6);  // 用b数组中前6个元素初始化v2

    // 将v2容器中的50、60、70插入到v1索引7的位置
    v1.insert(v1.begin() + 7, v2.begin() + 1, v2.begin() + 4);

    // 输出结果
    cout << "插入操作后:";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;

    return 0;
}

七、vector元素的删除

  1. pop_back()
    只能删除最后一个元素,无法指定位置。
  2. erase()
    会导致后续元素前移,迭代器可能失效。
  3. clear()
    只是清空元素,不改变容量(capacity)。
  4. erase-remove
    是标准删除指定值元素的高效方案。

示例代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 创建并初始化 vector
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);

    // 方法1: pop_back() 删除最后一个元素
    v.pop_back();  // 删除50
    cout << "pop_back() 后: ";
    for (auto num : v) cout << num << " ";  // 输出: 10 20 30 40
    cout << endl;

    // 方法2: erase(pos) 删除指定位置的元素
    v.erase(v.begin() + 1);  // 删除索引1处的元素 (20)
    cout << "erase(pos) 后: ";
    for (auto num : v) cout << num << " ";  // 输出: 10 30 40
    cout << endl;

    // 方法3: erase(pos1, pos2) 删除区间元素
    v.erase(v.begin() + 1, v.end());  // 删除索引1到末尾的所有元素
    cout << "erase(beg, end) 后: ";
    for (auto num : v) cout << num << " ";  // 输出: 10
    cout << endl;

    // 重置 vector
    v = { 10, 20, 30, 40, 50, 60, 70 };

    // 方法4: clear() 删除所有元素
    v.clear();
    cout << "clear() 后 size: " << v.size();  // 输出: 0

    return 0;
}

八、vector迭代器

构造迭代器

vector<int>::iterator it;

示例代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 定义整型数组
    int iArray[] = { 100, 1, 20, 30, 40 };

    // 创建vector容器并用数组初始化
    vector<int> vecIntA;
    vecIntA.assign(iArray, iArray + 5);  // 将数组元素赋值给vector

    // 构造迭代器
    vector<int>::iterator it;

    // 让迭代器指向vecIntA的第一个元素
    it = vecIntA.begin();

    // 通过迭代器遍历vector所有元素
    for (it = vecIntA.begin(); it != vecIntA.end(); it++) {
        cout << *it << " ";  // 输出当前迭代器指向的元素值
    }
    cout << endl;  // 输出:100 1 20 30 40

    // 重置迭代器位置
    it = vecIntA.begin();    // 指向第一个元素 (100)

    // 迭代器前进2个位置
    it = it + 2;             // 指向第三个元素 (20)
    cout << *it << endl;     // 输出:20

    // 迭代器后退2个位置
    it = it - 2;             // 返回第一个元素 (100)
    cout << *it << endl;     // 输出:100

    return 0;
}


九、迭代器失效问题

1. 什么是迭代器失效?

迭代器失效指的是在对容器进行修改操作后,之前获取的迭代器可能不再有效。此时,如果继续使用这些迭代器进行访问或操作,程序可能崩溃或行为异常。


2. vector 中常见导致迭代器失效的操作

操作迭代器失效情况说明
插入元素 (push_back, insert)可能导致所有迭代器失效(若发生扩容)容器扩容时,会重新分配内存,旧迭代器失效
删除元素 (erase, pop_back)被删除元素及其后的元素迭代器失效后续元素位置前移,相关迭代器失效
clear()所有迭代器失效容器清空,迭代器失效
不修改容器大小迭代器通常保持有效例如读取操作,不影响迭代器

3. 为什么会失效?

vector 底层是连续的内存数组。当发生扩容(容量不足时自动增长),会重新分配更大的内存块,并把原数据拷贝过去,旧内存释放,之前指向旧内存的迭代器就失效了。

删除元素时,后续元素会前移,导致它们的内存位置改变,因此指向这些元素的迭代器也失效。


4. 如何避免迭代器失效?

  • 避免在使用迭代器过程中修改容器结构(如插入、删除);
  • 插入或删除操作后,重新获取迭代器;
  • 使用索引访问替代迭代器访问(当可行时);
  • 对于需要频繁插入删除的场景,考虑使用链表(list)等不会因插入删除导致迭代器失效的容器。

示例代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 创建vector容器v
    vector<int> v;

    // 向vector尾部插入元素
    v.push_back(1);  // 插入第一个元素:1
    v.push_back(2);  // 插入第二个元素:2
    v.push_back(3);  // 插入第三个元素:3
    v.push_back(4);  // 插入第四个元素:4

    // 创建迭代器it,指向v的第四个元素位置(索引3,值为4)
    vector<int>::iterator it = v.begin() + 3;

    // 在迭代器位置插入元素8,并更新迭代器
    // insert操作返回指向新插入元素的新迭代器
    it = v.insert(it, 8); // 如果不给it重新赋值会失效会出错的

    // 输出新迭代器指向的元素值
    cout << *it << endl;  // 输出:8

    vector<int> cond = { 1, 2, 3, 3, 3, 3, 4, 5, 6 };

    for (auto it = cond.begin(); it != cond.end(); ) {
        if (*it == 3) {
            // 关键修正:接收 erase() 返回的新迭代器
            it = cond.erase(it);

            // 可选:输出被删除元素的后继值
            if (it != cond.end()) {
                cout << "后一个元素: " << *it << endl;
            }
        }
        else {
            it++;  // 仅当未删除时移动迭代器
        }
    }

    // 验证结果
    cout << "剩余元素: ";
    for (int num : cond) {
        cout << num << " ";
    }
    // 输出: 1 2 4 5 6 

    return 0;
}

十、敬请期待下一章deque

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值