目录
如需咨询请添加个人微信:a15135158368
欢迎叨扰,多多交流
`std::vector`
是 C++ 标准模板库 (STL) 中的一个动态数组容器(可变长数组),它能够存储类型相同的对象,并且在大小变化时自动管理内存(随时添加和删除元素)。
1. 基本概念
-
动态数组
std::vector
类似于普通的数组,但它的大小是动态的,可以根据需要自动调整。与普通数组不同的是,
std::vector
的大小可以在运行时增加或减少。 -
自动内存管理
std::vector
在内部自动管理内存分配和释放,避免了手动管理内存的复杂性。
2. 常用的构造函数
-
默认构造函数
创建一个空的
std::vector
。std::vector<int> vec;
-
指定大小的构造函数
创建一个包含 5 个元素的
std::vector
每个元素使用类型的默认构造函数初始化。
std::vector<int> vec(5);
-
指定大小和初始值的构造函数
创建一个包含 5 个元素的
std::vector
,每个元素都初始化为 10。std::vector<int> vec(5, 10);
-
初始化中有多个元素
vector<int> a{1, 2, 3, 4, 5};//数组a中有五个元素,数组长度就为5
-
复制构造函数
使用另一个
std::vector
初始化一个新的std::vector
。std::vector<int> vec2(vec1); //类型必须相同 std::vector<int> vec2 = vec1;
-
迭代器范围的构造函数
使用其他容器或数组的迭代器范围初始化
std::vector
。std::vector<int> vec(vec1.begin(), vec1.end());
-
二维容器初始化
#include <iostream> #include <vector> using namespace std; int main() { // 初始化一个 3x4 的二维 vector,所有元素初始化为 0 vector<vector<int>> vec(3, vector<int>(4, 0)); // 输出二维 vector 的内容 for (const auto& row : vec) { for (const auto& elem : row) { cout << elem << " "; } cout << endl; } return 0; }
3. 常用的成员函数
-
push_back()
在
std::vector
的末尾添加元素。vec.push_back(20);
-
pop_back()
移除
std::vector
末尾的元素。vec.pop_back();
-
size()
返回当前存储的元素数量。
std::cout << vec.size() << std::endl;
-
capacity()
返回当前分配的存储空间的容量(即在不重新分配内存的情况下,
std::vector
可以存储的元素个数)。std::cout << vec.capacity() << std::endl;
-
empty()
判断
std::vector
是否为空。if (vec.empty()) { std::cout << "Vector is empty." << std::endl; }
-
clear()
清除所有元素,使
std::vector
为空。vec.clear();
-
at()
返回指定位置的元素,带边界检查。
int val = vec.at(2);
-
operator[]
返回指定位置的元素,不带边界检查。
int val = vec[2];
-
insert()
在指定位置插入元素或多个元素。
vec.insert(vec.begin() + 1, 15); // 在第二个位置插入15
-
erase()
删除指定位置的元素或范围内的元素。
vec.erase(vec.begin() + 1); // 删除第二个元素
-
resize()
调整
std::vector
的大小,并可指定值。vec.resize(10); // 调整大小为10 vec.reszie(n, v); //将n个空间数值赋值为v, 如果没有默认赋值为0
//注意:如果之前指定过该空间的值,再次赋值时并不会覆盖。 //以下这个例子会证明 #include<bits/stdc++.h> using namespace std; void out(vector<int> &a) { for (auto &x: a) cout << x << " "; cout << "\n"; } int main() { vector<int> a(5, 1); out(a); // 1 1 1 1 1 a.resize(10, 2); out(a); // 1 1 1 1 1 2 2 2 2 2 a.resize(3, 3); out(a); // 1 1 1 return 0; }
-
reserve()
预先分配内存,以避免在增加元素时多次重新分配内存。
vec.reserve(100);
4. 迭代器
类似指针,迭代器就是充当指针的作用。vi[i] 等价于 *(vi.begin() + i)
-
begin()
和end()
返回
std::vector
的起始和结束迭代器。-
end()返回的是最后一个元素的后一位置的地址
//auto关键字:自动推导变量类型(注意:变量必须在定义时初始化;可能忽略const和引用&,如需使用需明确声明) for (auto it = vec.begin(); it != vec.end(); ++it) { std::cout << *it << " "; } std::cout << std::endl;
-
-
rbegin()
和rend()
返回
std::vector
的逆向迭代器。for (auto it = vec.rbegin(); it != vec.rend(); ++it) { std::cout << *it << " "; } std::cout << std::endl;
5. 内存管理
-
shrink_to_fit()
将
std::vector
的容量减少到与当前大小匹配,释放未使用的内存。vec.shrink_to_fit();
-
allocator_type
可以自定义
std::vector
的内存分配器。
6.更多成员函数汇总
代码 | 算法复杂度 | 返回值类型 | 含义 |
---|---|---|---|
c.front() | O(1)O(1) | 引用 | 返回容器中的第一个数据 |
c.back() | O(1)O(1) | 引用 | 返回容器中的最后一个数据 |
c.at(idx) | 引用 | 返回 c[idx] ,会进行边界检查,如果越界会报错,比直接使用 [] 更好一些,常在项目中使用 | |
c.size() | O(1)O(1) | 返回实际数据个数(unsigned类型) | |
c.begin() | O(1)O(1) | 迭代器 | 返回首元素的迭代器(通俗来说就是地址) |
c.end() | O(1)O(1) | 迭代器 | 返回最后一个元素后一个位置的迭代器(地址) |
c.empty() | O(1)O(1) | bool | 判断是否为空,为空返回真,反之返回假 |
c.reserve(sz) | 为数组提前分配sz 的内存大小,即改变了 capacity 的大小,主要是为了防止在 push_back 过程中多次的内存拷贝 | ||
c.assign(beg, end) | 将另外一个容器[x.begin(), x.end()) 里的内容拷贝到c 中 | ||
c.assign(n, val) | 将n 个val 值拷贝到c 数组中,这会清除掉容器中以前的内容,c 数组的size 将变为n ,capacity 不会改变 | ||
c.pop_back() | O(1)O(1) | 删除最后一个数据 | |
c.push_back(element) | O(1)O(1) | 在尾部加一个数据 | |
c.emplace_back(ele) | O(1)O(1) | 在数组中加入一个数据,和 push_back 功能基本一样,在某些情况下比它效率更高,支持传入多个构造参数 | |
c.clear() | O(N)O(N) | 清除容器中的所有元素 | |
c.resize(n, v) | 改变数组大小为n ,n 个空间数值赋为v ,如果没有默认赋值为0 | ||
c.insert(pos, x) | O(N)O(N) | 向任意迭代器pos 插入一个元素x | |
例:c.insert(c.begin() + 2, -1) | 将-1 插入c[2] 的位置 | ||
c.erase(first, last) | O(N)O(N) | 删除[first, last) 的所有元素 |
礼貌转载,感谢!
来源: 行码棋 作者: 行码棋 链接: C++ STL总结 | 行码棋
7.vector
函数使用实例代码
/**
******************************************************************************
* @file : vector_study.cpp
* @author : niuniu
* @brief : 一个 `std::vector` 容器的实例
* @attention : None
* @date : 2024/8/28
******************************************************************************
*/
#include <iostream>
#include <vector>
int main() {
// 创建一个存储 int 类型的 vector 容器
std::vector<int> vec;
// 使用 push_back() 在 vector 的末尾添加元素
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
std::cout << "使用`push_back`将元素压入后的结果为 : ";
for (int val : vec) {
std::cout << val << " "; // 输出: 10 20 30
}
std::cout << std::endl;
// 使用 pop_back() 移除末尾的元素
vec.pop_back();
std::cout << "使用`pop_back`移除末尾元素后的结果为 : ";
for (int val : vec) {
std::cout << val << " "; // 输出: 10 20
}
std::cout << std::endl;
// 使用 size() 获取当前元素数量
std::cout << "当前容器的元素数量为(size) : " << vec.size() << std::endl; // 输出: 2
// 使用 capacity() 获取当前分配的容量
std::cout << "当前分配的容量为(capacity) : " << vec.capacity() << std::endl; // 输出: 4
// 使用 empty() 判断 vector 是否为空
if (!vec.empty()) {
std::cout << "容器不为空" << std::endl;
}
// 使用at()访问元素
try //异常处理机制,如果在try语句中发生异常,会跳到catch语句
{
std::cout << "索引1处的元素为 (at) : " << vec.at(1) << std::endl;
}
catch (const std::out_of_range& e) //根据异常的类型,决定是否处理该异常,参数指定可以处理异常的类型
{
//what()是异常对象的一个成员函数,返回值会描述错误的消息
std::cout << "错误:超出范围 (what) : " << e.what() << std::endl;
}
// 使用 operator[] 访问指定位置的元素(不带边界检查)
std::cout << "索引0处的元素为 (重载索引[]) : " << vec[0] << std::endl; // 输出: 10
// 使用 insert() 在指定位置插入元素
vec.insert(vec.begin() + 1, 15);
std::cout << "在索引1处插入后 (insert) : ";
for (int val : vec) {
std::cout << val << " "; // 输出: 10 15 20
}
std::cout << std::endl;
// 使用 erase() 删除指定位置的元素
vec.erase(vec.begin());
std::cout << "删除第一个元素后 (erase) : ";
for (int val : vec) {
std::cout << val << " "; // 输出: 15 20
}
std::cout << std::endl;
// 使用 resize() 调整 vector 的大小
vec.resize(4, 100); // 如果增加大小,使用 100 进行填充
std::cout << "调整为4个元素后 (resize) : ";
for (int val : vec) {
std::cout << val << " "; // 输出: 15 20 100 100
}
std::cout << std::endl;
// 使用 reserve() 预先分配内存
vec.reserve(10);
std::cout << "储备后容量(10) (reserve) : " << vec.capacity() << std::endl; // 输出: 10
// 使用 clear() 清空所有元素
vec.clear();
std::cout << "清除后的尺寸 (clear) : " << vec.size() << std::endl; // 输出: 0
std::cout << "清除后的容量 (clear) : " << vec.capacity() << std::endl; // 输出: 10
// 使用 begin() 和 end() 获取起始和结束迭代器
vec.push_back(50);
vec.push_back(60);
std::cout << "使用begin()和end() 遍历: ";
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " "; // 输出: 50 60
}
std::cout << std::endl;
// 使用 rbegin() 和 rend() 获取逆向迭代器
std::cout << "使用rbegin()和rend(): ";
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
std::cout << *rit << " "; // 输出: 60 50
}
std::cout << std::endl;
// 使用 shrink_to_fit() 释放未使用的内存
vec.shrink_to_fit();
std::cout << "收缩后的容量 : " << vec.capacity() << std::endl; // 输出: 2
// 使用 allocator_type 自定义内存分配器(高级用法,不常见)
std::vector<int, std::allocator<int>> customAllocatorVec;
customAllocatorVec.push_back(70);
std::cout << "使用自定义分配器 (allocator_type): " << customAllocatorVec[0] << std::endl; // 输出: 70
return 0;
}