【c++】【STL库-vector】
1.定义vector
C++ 中的 vector 是一种序列容器,它允许你在运行时动态地插入和删除元素。
vector 是基于数组的数据结构,但它可以自动管理内存,这意味着你不需要手动分配和释放内存。
#include<vector>//引用的头文件
std::vector<int> myVector; // 创建一个存储整数的空 vector
std::vector<int> myVector={1,2,3,4,5};//常见一个初始化包含元素的vector
std::vector<int> myVector(5); // 创建一个包含 5 个整数的 vector,每个值都为默认值(0)
std::vector<int> myVector(5, 10); // 创建一个包含 5 个整数的 vector,每个值都为 1
2.访问vector中的元素
int main() {
// 初始化一个 vector(元素类型 int,初始值 [10, 20, 30, 40, 50],索引 0~4)
vector<int> vec = {10, 20, 30, 40, 50};
cout << "原始 vector:";
for (int &val : vec)
{cout << val << " ";}
}
2.1 at访问
at() 成员函数(安全访问,带边界检查)
语法:vec.at(index)
特点:会检查索引是否越界,越界时抛出 std::out_of_range 异常(可捕获处理);效率略低于 []
int main()
{
// 初始化一个 vector(元素类型 int,初始值 [10, 20, 30, 40, 50],索引 0~4)
vector<int> vec = {10, 20, 30, 40, 50};
cout << "原始 vector:";
for (int &val : vec)
{cout << val << " ";}
cout << "\n=== at() 安全访问 ===" << endl;
cout << "索引 2 的元素:" << vec.at(2) << endl; // 输出 30
// 2. 修改元素(返回引用,支持读写)
vec.at(3) = 400; // 将索引 3 的元素从 40 改为 400
cout << "修改后 vector:";
for (int &val : vec) cout << val << " "; // 输出 10 20 30 400 500
cout << endl;
// 3. 越界访问(抛出异常,可捕获)
try {
vec.at(10); // 索引 10 超出范围,抛出异常
} catch (const out_of_range& e) {
cout << "at() 越界错误:" << e.what() << endl; // 输出错误信息,程序不崩溃
}
}
2.2 operator[]访问
[] 下标运算符(最常用,效率最高)
语法:vec[index](索引从0开始)
特点:直接内存访问,执行效率最佳;但不进行边界检查,越界访问可能引发未定义行为(程序崩溃或内存污染)[] 下标运算符(最常用,效率最高)
int main()
{
// 初始化一个 vector(元素类型 int,初始值 [10, 20, 30, 40, 50],索引 0~4)
vector<int> vec = {10, 20, 30, 40, 50};
cout << "原始 vector:";
for (int &val : vec)
{cout << val << " ";}
cout << "=== [] 下标访问 ===" << endl;
cout << "索引 0 的元素:" << vec[0] << endl; // 输出 10
cout << "索引 3 的元素:" << vec[3] << endl; // 输出 40
// 2. 修改元素(返回引用,支持读写)
vec[1] = 200; // 将索引 1 的元素从 20 改为 200
vec[4] = 500; // 将索引 4 的元素从 50 改为 500
cout << "修改后 vector:";
for (int val : vec) cout << val << " "; // 输出 10 200 30 40 500
cout << endl;
// 3. 注意:越界访问(危险!未定义行为)
// vec[10] = 999; // 索引 10 超出范围(0~4),可能崩溃,编译器不报错
}
2.3迭代器访问
2.3.1普通迭代器
// 1. 普通迭代器(读写)
int main()
{
// 初始化一个 vector(元素类型 int,初始值 [10, 20, 30, 40, 50],索引 0~4)
vector<int> vec = { 10, 20, 30, 40, 50 };
cout << "原始 vector:";
for (int& val : vec)
{
cout << val << " ";
}
cout << "\n=== 普通迭代器(可读写) ===" << endl;
vector<int>::iterator it = vec.begin(); // it 指向第一个元素(10)
for (it; it != vec.end(); it++)
{
cout << *it << endl;
}
cout << endl;
it= vec.begin();
for (it; it != vec.end(); it++)
{
*it += 10;
cout << *it << endl;
}
return 0;
}
2.3.2 常性迭代器
(只可读元素但是不可以修改值)
int main()
{
// 初始化一个 vector(元素类型 int,初始值 [10, 20, 30, 40, 50],索引 0~4)
vector<int> vec = { 10, 20, 30, 40, 50 };
cout << "原始 vector:";
for (int& val : vec)
{
cout << val << " ";
}
cout << "const 迭代器遍历(只读):"<<endl;
vector<int>::const_iterator cit = vec.cbegin(); // cbegin() 返回 const 迭代器
for (; cit != vec.cend(); ++cit) {
cout << *cit << " "; // 正常读取,输出 200 400 60 800 1000
// *cit = 0; // 编译错误:const 迭代器禁止修改元素
}
cout << endl;
return 0;
}
2.3.3 逆置迭代器
2.3 at和operator[]的区别\

3.插入元素向vector
3.1 push_back
插入元素,首先我们会建立一个副本,如果是拷贝构造函数,我们需要先拷贝构造对象(定位new)一个副本放在这个容器空间上面
插入元素,如果是移动构造的话,我们就不需要进行额外的拷贝,直接将对象移动到容器里面
①如果插入元素之前没有可以使用的空间,我们就需要先扩容
②
拷贝构造:如果说push_back的是一个临时对象,拷贝构造一个临时副本对象,然后把这个副本通过定位new的方式构造在这个vector空间(是通过vector的底层分配器std::allocator与西安分配一块连续的内存空间)上面;
移动构造:将对象资源直接转移到这个vector空间上面;
③当再次通过push_back插入对象时,我们需要扩容一块一个大的新的空间,此时我们就要把原来空间里面的对象再拷贝一份到新的空间里面,释放原来的那片空间和原来空间上面的对象。
上面我们不难看出,如果预先没有预留空间,我们需要频繁的释放空间和开辟新的空间(通常是原容量的1.5倍~2倍),将原数组的所有元素拷贝/移动到新的内存;释放原来的内存空间。
所以我们就需要再push_back的时候进行reserve.
此外我们进行插入操作的时候一般都是进行尾插,因为vector是一个连续的动态数组,如果你在头插或者中间插入插入,他就需要经元素一个一个的向后挪动。
3.2 emplace_back
他解决了我们需要频繁拷贝,移动资源,和频繁的释放空间和扩容操作。
所以我们就采用了emplace_back,又称原位原位构造,顾名思义,就是让我直接再vector空间上面进行构造对象。
3.3 insert
插入单个元素
iterator insert(iterator pos, const T& value); // 在pos位置插入value
iterator insert(iterator pos, T&& value); // 使用移动语义插入value(C++11)
插入多个相同元素
iterator insert(iterator pos, size_t count, const T& value); // 在pos位置插入count个value
插入元素区间(迭代器范围)
template <class InputIt>
iterator insert(iterator pos, InputIt first, InputIt last); // 在pos位置插入[first, last)范围内的元素
3.4 emplace_back和push_back区别

#include <vector>
#include <string>
using namespace std;
class Person {
public:
Person(string name, int age) : name_(name), age_(age) {}
private:
string name_;
int age_;
};
int main() {
vector<Person> v;
// push_back:先构造临时Person,再移动到vector
v.push_back(Person("Alice", 20));
// emplace_back:直接在vector尾部原地构造Person
v.emplace_back("Bob", 22);
return 0;
}
4.reserve和resize

vector<int> vec{1,2,3};
vec.reserve(10);
cout << vec.size(); // 输出 3(元素数量不变)
cout << vec.capacity();// 输出 10(内存已预分配)
vector<int> vec{1,2,3};
vec.resize(5); // 新增2个元素,默认值为0 → vec = {1,2,3,0,0}
cout << vec.size(); // 输出 5
cout << vec.capacity();// 输出 ≥5
vec.resize(2); // 销毁后3个元素 → vec = {1,2}
cout << vec.size(); // 输出 2
5.assign
assign() 是 vector 的成员函数,用于替换容器中的所有现有元素(先清空原有元素,再插入新元素)。它会直接改变 vector 的 size,并在新元素数量超过当前容量时调整 capacity。
形式 1:assign(n, val)
- 参数:
n:整数,指定要插入的新元素数量val:与 vector 元素类型匹配的值,指定每个新元素的值
- 功能:清空原有元素 → 插入
n个值为val的元素
vector<int> vec{1,2,3}; // 原内容:{1,2,3}
vec.assign(4, 10); // 清空原元素 → 插入4个10
// 结果:vec = {10,10,10,10},size=4,capacity≥4
形式 2:assign(first, last)
- 参数:
first/last:迭代器(指针也可),指定元素范围 [first, last)(左闭右开)
- 功能:清空原有元素 → 拷贝/移动 [first, last) 范围内的元素
- 适用场景:从其他容器(数组、vector、list 等)批量导入元素
vector<int> vec{1,2,3}; // 原内容:{1,2,3}
int arr[] = {100,200,300,400};
// 插入数组中 arr+1 到 arr+3 的元素(200、300)
vec.assign(arr+1, arr+3);
// 结果:vec = {200,300},size=2,capacity≥2
// 从另一个vector导入
vector<int> tmp{5,6,7};
vec.assign(tmp.begin(), tmp.end()); // 结果:vec = {5,6,7}
形式 3:assign(initializer_list)
- 参数:
initializer_list:初始化列表 {元素1, 元素2,…}
- 功能:清空原有元素 → 插入初始化列表中的所有元素(C++11+支持)
vector<int> vec{1,2,3}; // 原内容:{1,2,3}
vec.assign({8,9,10,11}); // 清空原元素 → 插入8、9、10、11
// 结果:vec = {8,9,10,11},size=4,capacity≥4
特殊情况
- 当
n=0时:assign(0, val)等价于清空 vector(size=0),但 capacity 不变(需使用shrink_to_fit()释放内存)vec.assign(0, 0); // 清空所有元素,size=0,capacity不变 - 内存变化:
- 自动扩容(当新元素数量 > 当前 capacity)
- 不会主动缩容(如原 capacity=10,assign(2, 0) 后 capacity 仍为 10)
- 元素析构:
- 对于类对象,assign() 会先调用所有原有元素的析构函数,再构造新元素,避免内存泄漏assign() 是 vector 的成员函数,作用是替换容器中所有现有元素(先清空原元素,再插入新元素),会直接改变 size,也可能间接改变 capacity(如果新元素数量超过当前容量)。
6.迭代器失效
6.1迭代器失效本质
迭代器本质是 “容器元素的内存指针 / 索引封装”,当容器底层内存布局改变(如扩容、元素移动)、元素被删除时,迭代器指向的地址 / 逻辑位置失效,此时解引用或操作迭代器会导致 UB(未定义行为)。
6.2迭代器失效场景

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)