- C++
C++ Vector 学习笔记
- 2025-5-1 20:03:06 @
📚 一、vector 是什么?
在C++中,vector 是一个动态数组,属于 STL(标准模板库) 的一部分。它可以根据需要自动扩容,非常灵活。
特点:
- 支持随机访问(像数组一样)
- 可以动态增长或缩小
- 提供丰富的操作函数(添加、删除、查找等)
🧰 二、如何使用 vector?
要使用 vector,首先需要包含头文件:
#include <iostream>
#include <vector> // 使用 vector 必须包含这个头文件
using namespace std;
🧱 三、定义和初始化 vector
✅ 定义空的 vector(默认构造函数):
vector<int> v; // 创建一个整型 vector,初始为空
✅ 初始化 vector 的几种方式:
方式1:直接赋值多个元素(C++11及以上支持)
vector<int> v = {1, 2, 3, 4, 5};
方式2:指定大小和初始值
vector<int> v(5, 10); // 创建5个元素,每个都是10:{10, 10, 10, 10, 10}
方式3:复制另一个 vector
vector<int> v1 = {1, 2, 3};
vector<int> v2(v1); // v2 复制了 v1 的内容
方式4:通过迭代器区间初始化(后面讲)
vector<int> v3(v1.begin(), v1.end()); // v3 和 v1 内容一样
🔍 四、常用操作函数详解 + 示例
1. 添加元素:push_back()
将元素添加到 vector 的末尾。
vector<int> v;
v.push_back(10); // 加入10
v.push_back(20); // 加入20
// v 现在是:[10, 20]
2. 访问元素:下标访问 [i]
或 at(i)
cout << v[0] << endl; // 输出第一个元素:10
cout << v.at(1) << endl; // 输出第二个元素:20
⚠️ 注意:
at()
会做边界检查,越界会抛出异常;[]
不检查,效率高但不安全。
3. 获取 vector 长度:size()
cout << "当前 vector 中有 " << v.size() << " 个元素" << endl;
4. 判断是否为空:empty()
if (v.empty()) {
cout << "vector 是空的";
} else {
cout << "vector 不是空的";
}
5. 删除最后一个元素:pop_back()
v.pop_back(); // 删除最后一个元素(即20)
// v 现在是:[10]
6. 清空 vector:clear()
v.clear(); // 所有元素都被清除
// v 现在是空的
7. 修改元素
可以直接通过下标修改:
v[0] = 100;
cout << v[0]; // 输出 100
8. 插入元素:insert()
插入到某个位置前面。
v.insert(v.begin() + 1, 50); // 在第1个位置前插入50
// 如果原vector为 [10, 20],现在变成 [10, 50, 20]
9. 删除指定位置元素:erase()
v.erase(v.begin() + 1); // 删除第1个位置上的元素
// 如果原vector为 [10, 50, 20],现在变成 [10, 20]
10. 遍历 vector
方法一:使用 for 循环 + 下标
for(int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
方法二:使用迭代器(iterator)
for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
方法三:范围 for 循环(推荐,C++11起)
for(int num : v) {
cout << num << " ";
}
📦 五、vector 的容量与性能相关函数
查看当前容量:capacity()
cout << "当前容量: " << v.capacity() << endl;
手动调整容量:reserve(n)
预先分配内存空间,提高效率。
v.reserve(100); // 预留100个int的空间
缩小内存占用:shrink_to_fit()
释放未使用的内存空间。
v.shrink_to_fit();
📌 六、vector 作为函数参数传递
传参方式(建议使用引用)
void printVector(const vector<int>& v) {
for(int num : v) {
cout << num << " ";
}
cout << endl;
}
int main() {
vector<int> v = {1, 2, 3};
printVector(v);
return 0;
}
🧪 七、完整示例代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 定义并初始化 vector
vector<int> v = {1, 2, 3};
// 添加元素
v.push_back(4);
v.push_back(5);
// 输出长度
cout << "当前 vector 长度:" << v.size() << endl;
// 遍历输出
cout << "vector 内容:";
for(int num : v) {
cout << num << " ";
}
cout << endl;
// 修改元素
v[0] = 100;
// 插入元素
v.insert(v.begin() + 2, 99);
// 删除元素
v.pop_back();
// 再次遍历输出
cout << "修改后的内容:";
for(int num : v) {
cout << num << " ";
}
return 0;
}
📝 八、总结知识点表格
操作 | 函数 | 说明 |
---|---|---|
添加元素 | push_back(x) |
在末尾添加元素x |
删除末尾元素 | pop_back() |
删除最后一个元素 |
获取长度 | size() |
返回当前元素个数 |
判断是否为空 | empty() |
是否为空 |
清空所有元素 | clear() |
清空vector |
插入元素 | insert(pos, x) |
在pos前插入x |
删除元素 | erase(pos) |
删除pos位置的元素 |
访问元素 | v[i] / at(i) |
访问第i个元素 |
获取容量 | capacity() |
当前可容纳的最大元素数 |
预分配空间 | reserve(n) |
提前分配n个空间 |
收缩内存 | shrink_to_fit() |
释放多余内存 |
✅ 九、学习建议
- 初学者重点掌握:
push_back
、size
、[]
、pop_back
、循环遍历
- 进阶学习:
insert
、erase
、reserve
、capacity
- 实战应用:可以用 vector 存储用户输入数据、处理列表、模拟栈/队列等结构
13 条评论
-
admin SU @ 2025-5-14 18:55:57
#include<iostream> #include <vector> // 使用 vector 必须包含这个头文件 using namespace std; int main() { vector<int> v = {1, 2, 3, 9, 5}; /*vector<int>::iterator it = v.begin(); for (it = v.begin(); it != v.end(); it++) { cout << *it << " "; } puts(""); //int a = 6; auto a = 6;//auto初始化自推导类型 cout<<a<<endl; for (auto it = v.begin(); it != v.end(); it++) { cout << *it << " "; } puts("");*/ for(int num : v) { cout << num << " "; } return 0; }
-
2025-5-14 18:53:26@
#include <iostream> #include <vector> // 使用 vector 必须包含这个头文件 using namespace std; //vector<int> v; // 创建一个整型 vector,初始为空 vector<int> v = {1, 2, 3, 9, 5}; //vector<int> v(7, 10); // 创建7个元素,每个都是10:{10,10,10, 10, 10, 10, 10} //vector<int> v1 = {1, 2, 3}; //vector<int> v2(v1); // v2 拷贝复制了 v1 的内容 //vector<int> v3(v1.begin(), v1.end()); // v3 和 v1 内容一样 int main() { //迭代器 // //cout<<*v.begin()<<endl; // cout<<*(--v.end())<<endl; // cout<<*(v.end()-2)<<endl; //指针 //v[0] = 100; //v.at(1) = 200; //cout << v[0]; // 输出 100 //v.push_back(56); //v.push_back(123); //v.insert(v.begin()+1,9999); v.erase(v.begin()+2); int len = v.size(); for (int i = 0; i < len; i++) { cout << v[i] << " "; } puts(""); return 0; }
-
2025-5-14 18:53:15@
#include<iostream> #include <vector> // 使用 vector 必须包含这个头文件 using namespace std; int main() { vector<int> v = {1, 2, 3, 9, 5}; vector<int>::iterator it = v.begin(); for (it = v.begin(); it != v.end(); it++) { cout << *it << " "; } puts(""); //int a = 6; auto a = 6;//auto初始化自推导类型 cout<<a<<endl; for (auto it = v.begin(); it != v.end(); it++) { cout << *it << " "; } puts(""); return 0; }
-
2025-5-14 18:16:43@
#include <iostream> #include <vector> // 使用 vector 必须包含这个头文件 using namespace std; vector<int> v; // 创建一个整型 vector,初始为空 int main() { v.push_back(56); v.push_back(123); int len = v.size(); for(int i = 0;i< len;i++){ cout<<v[i]<<" "; } puts(""); return 0; }
-
2025-5-11 14:17:30@
#include<bits/stdc++.h> using namespace std; /*void printVector(vector<int> v) {//拷贝传递 for (int num : v) { cout << num << " "; } cout << endl; }*/ /*void printVector(vector<int>& v) {//传引用传递 for (int num : v) { cout << num << " "; } cout << endl; }*/ void printVector(const vector<int>& v) {//传常量引用传递 for (int num : v) { cout << num << " "; } cout << endl; } int main() { vector<int> v = {1, 2, 3}; printVector(v); return 0; }
-
2025-5-11 14:10:43@
#include<bits/stdc++.h> using namespace std; vector<int> v = {1,3,8}; int main() { vector<int>::iterator it = v.begin(); for(it = v.begin();it!=v.end();it++){ cout<<(*it)<<" "; } return 0; }
-
2025-5-11 14:10:30@
#include<bits/stdc++.h> using namespace std; vector<int> v = {1,3,8}; int main() { for(int i : v) { cout << i << " "; } return 0; }
-
2025-5-11 13:57:41@
#include<bits/stdc++.h> using namespace std; vector<int> v = {1,3,8}; // 创建一个整型 vector,初始为空 int main() { //v.insert(v.begin() + 1, 50);//迭代器 指针 //cout<<v.at(0)<<endl; //cout<<*v.begin()<<endl; int len = v.size(); for(int i = 0;i<len;i++){ cout<<v[i]<<" "; } cout<<endl; v.insert(v.begin()+3, 50); len = v.size(); for(int i = 0;i<len;i++){ cout<<v[i]<<" "; } cout<<endl; return 0; }
-
2025-5-11 13:42:35@
在C++的标准库中,
std::vector
的push_back
和emplace_back
都用于在容器尾部添加元素,但二者存在一些关键差异:-
参数传递方式
push_back
:接受已构造的对象作为参数,可以是左值或右值。emplace_back
:接受构造对象所需的参数包,直接在容器内存中构造对象。
-
构造过程
push_back
:先构造临时对象,再通过拷贝/移动构造函数将其添加到容器。emplace_back
:直接在容器内存中构造对象,省略临时对象的创建和拷贝/移动操作。
-
性能差异
- 对于可直接构造的类型(如基本类型、
std::string
),二者性能接近。 - 对于构造代价较高的复杂对象,
emplace_back
通常更高效。
- 对于可直接构造的类型(如基本类型、
-
特殊场景支持
emplace_back
可以直接构造参数包对应的对象,例如接受参数列表构造的对象(如std::pair
、自定义类)。push_back
需要先手动构造对象,再传递给函数。
示例对比:
#include <vector> #include <string> #include <iostream> struct Person { std::string name; int age; // 带参数的构造函数 Person(const std::string& n, int a) : name(n), age(a) { std::cout << "Constructing Person: " << name << ", " << age << std::endl; } // 拷贝构造函数 Person(const Person& other) : name(other.name), age(other.age) { std::cout << "Copy constructing Person: " << name << ", " << age << std::endl; } // 移动构造函数 Person(Person&& other) noexcept : name(std::move(other.name)), age(other.age) { std::cout << "Moving Person: " << name << ", " << age << std::endl; } }; int main() { std::vector<Person> people; std::cout << "Using push_back with temporary object:" << std::endl; people.push_back(Person("Alice", 30)); // 先构造临时对象,再移动到容器 std::cout << "\nUsing push_back with lvalue:" << std::endl; Person bob("Bob", 25); people.push_back(bob); // 拷贝构造 std::cout << "\nUsing emplace_back:" << std::endl; people.emplace_back("Charlie", 35); // 直接在容器内构造对象 return 0; }
输出结果:
Using push_back with temporary object: Constructing Person: Alice, 30 Moving Person: Alice, 30 Using push_back with lvalue: Constructing Person: Bob, 25 Copy constructing Person: Bob, 25 Using emplace_back: Constructing Person: Charlie, 35
总结:
- 优先使用
emplace_back
,尤其是需要构造复杂对象时。 - 仅当需要精确控制构造过程(如调用特定重载)或兼容旧代码时,使用
push_back
。
-
-
2025-5-11 13:42:19@
好的,让我们用一个生活中的例子来理解
push_back
和emplace_back
的区别。餐厅比喻
假设你要开一家餐厅,顾客点菜后,你需要把菜送到顾客桌上:
- push_back:相当于厨师先把菜做好放在厨房的盘子里(创建临时对象),然后服务员把这盘菜端到顾客桌上(拷贝或移动到容器)。
- emplace_back:相当于厨师直接在顾客的餐桌上做菜(直接在容器内存中构造对象),省去了端盘子的步骤。
代码示例解释
假设我们有一个
Person
类,代表餐厅的顾客:struct Person { std::string name; int age; // 构造函数:创建一个新顾客 Person(const std::string& n, int a) : name(n), age(a) { std::cout << "创建顾客: " << name << ", 年龄: " << age << std::endl; } // 拷贝构造函数:复制顾客信息 Person(const Person& other) : name(other.name), age(other.age) { std::cout << "复制顾客: " << name << std::endl; } };
现在我们要把顾客添加到餐厅的顾客列表(
vector
)中:#include <vector> #include <string> int main() { std::vector<Person> customers; // 使用 push_back 添加顾客 std::cout << "使用 push_back:" << std::endl; customers.push_back(Person("小明", 20)); // 使用 emplace_back 添加顾客 std::cout << "\n使用 emplace_back:" << std::endl; customers.emplace_back("小红", 22); return 0; }
运行结果对比
使用 push_back: 创建顾客: 小明, 年龄: 20 复制顾客: 小明 // 临时对象被复制到容器中 使用 emplace_back: 创建顾客: 小红, 年龄: 22 // 直接在容器中构造,无需复制
关键区别总结
操作 push_back emplace_back 步骤 先创建对象 → 再复制到容器 直接在容器中创建对象 效率 可能需要额外的复制/移动操作 通常更高效(尤其对复杂对象) 使用场景 需要传递已存在的对象 直接传递构造参数(如字符串、数字) 示例 vec.push_back(Person("a",1))
vec.emplace_back("a", 1)
什么时候用哪个?
- emplace_back:当你需要添加的对象需要通过参数构造时(例如上面的
Person
需要名字和年龄),直接使用emplace_back
更简洁高效。 - push_back:当你已经有一个现成的对象,需要添加到容器中时,使用
push_back
。
// 已有对象,用 push_back Person p("小张", 25); customers.push_back(p); // 直接构造,用 emplace_back customers.emplace_back("小李", 23);
为什么需要两个功能?
在C++早期只有
push_back
,但后来发现很多时候我们是直接构造新对象并添加到容器中,中间的临时对象和复制过程显得多余。于是C++11引入了emplace_back
,让代码更简洁,性能更优。对于初学者,建议优先使用
emplace_back
,因为它能处理所有push_back
的场景,而且通常更高效。 -
2025-5-11 13:40:37@
#include<iostream> #include <vector> // 使用 vector 必须包含这个头文件 using namespace std; //int arr[200];//静态数组 vector<int> v; // 创建一个整型 vector,初始为空 int main() { //vector cout<<v.size()<<endl; v.push_back(6); v.push_back(10); cout<<v.size()<<endl; cout<<v[0]<<" "<<v[1]<<endl; return 0; }
-
2025-5-1 20:12:13@
C++ Vector 排序教程(配合 )
📚 一、前言:为什么需要排序?
在编程中,我们经常需要对数据进行排序。C++ 中的
vector
是一个非常灵活的动态数组容器,我们可以使用标准库中的<algorithm>
头文件提供的函数轻松实现排序。
🧰 二、准备知识
✅ 包含头文件:
#include <iostream> #include <vector> #include <algorithm> // 必须包含这个头文件才能使用 sort 函数 using namespace std;
🎯 三、默认排序:升序排列
std::sort()
是<algorithm>
提供的一个函数,可以对任意容器的数据进行排序。示例代码:
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> nums = {5, 2, 9, 1, 3}; // 对整个 vector 进行默认升序排序 sort(nums.begin(), nums.end()); // 输出排序后的结果 cout << "升序排序后的 vector:" << endl; for(int num : nums) { cout << num << " "; } return 0; }
输出:
升序排序后的 vector: 1 2 3 5 9
🔽 四、自定义排序:降序排列
如果我们想按从大到小排序,就需要自定义比较规则。
方法一:使用
<functional>
中的greater<>
#include <iostream> #include <vector> #include <algorithm> #include <functional> // 使用 greater<int>() using namespace std; int main() { vector<int> nums = {5, 2, 9, 1, 3}; // 使用 greater<int>() 实现降序排序 sort(nums.begin(), nums.end(), greater<int>()); cout << "降序排序后的 vector:" << endl; for(int num : nums) { cout << num << " "; } return 0; }
输出:
降序排序后的 vector: 9 5 3 2 1
🧩 五、自定义排序规则:使用 lambda 表达式(推荐)
对于更复杂的排序逻辑,比如奇偶排序、绝对值排序等,我们可以使用 lambda 表达式 自定义排序规则。
示例:按绝对值从小到大排序
#include <iostream> #include <vector> #include <algorithm> #include <cmath> // abs() using namespace std; int main() { vector<int> nums = {-5, -1, 3, -2, 4}; // 按照绝对值大小排序 sort(nums.begin(), nums.end(), [](int a, int b) { return abs(a) < abs(b); }); cout << "按绝对值从小到大排序:" << endl; for(int num : nums) { cout << num << " "; } return 0; }
输出:
按绝对值从小到大排序: -1 -2 3 4 -5
🧱 六、二维 vector 的排序(进阶)
假设我们有一个二维
vector<vector<int>>
,我们要按照每一行的第一个元素排序。示例:按每行第一个元素排序
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<vector<int>> matrix = { {3, 2}, {1, 5}, {2, 4} }; // 按照每行第一个元素从小到大排序 sort(matrix.begin(), matrix.end(), [](vector<int>& a, vector<int>& b) { return a[0] < b[0]; }); cout << "按第一列排序后的矩阵:" << endl; for(auto& row : matrix) { for(int num : row) { cout << num << " "; } cout << endl; } return 0; }
输出:
按第一列排序后的矩阵: 1 5 2 4 3 2
📝 七、总结知识点表格
功能 方法 说明 升序排序 sort(vec.begin(), vec.end())
默认从小到大排序 降序排序 sort(vec.begin(), vec.end(), greater<int>())
需要包含 <functional>
自定义排序 sort(vec.begin(), vec.end(), [](int a, int b){ return ... })
使用 Lambda 表达式定义规则 二维 vector 排序 同样使用 sort()
和 Lambda可以根据子 vector 的某个元素排序
✅ 八、学习建议
- 初学者重点掌握:升序排序、降序排序、Lambda 简单使用
- 进阶学习:结合结构体、字符串排序、多条件排序
- 实战应用:可用于学生分数排序、商品价格排序、排行榜系统等场景
-
2025-5-1 20:05:31@
二维 vector 的使用方法
二维
vector
在C++中可以看作是一个动态的二维数组,非常适合用于需要存储矩阵、表格等数据结构的应用场景。下面我们将详细介绍如何定义、初始化、访问和操作二维vector
。一、包含头文件
首先,要使用
vector
,我们需要包含<vector>
头文件,并且为了简化代码,我们可以使用using namespace std;
:#include <iostream> #include <vector> using namespace std;
二、定义与初始化
1. 定义空的二维
vector
vector<vector<int>> matrix; // 创建一个空的二维 vector,类型为 int
2. 初始化指定大小的二维
vector
- 指定行数和列数,所有元素初始化为默认值(如
int
类型为0)
vector<vector<int>> matrix(3, vector<int>(4)); // 创建3行4列的二维 vector,初始值为0
3. 使用初始化列表
- 直接用初始化列表创建二维
vector
(C++11及以上支持)
vector<vector<int>> matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; // 创建一个3x3的二维 vector
三、访问元素
可以通过双重下标的方式访问二维
vector
中的元素,类似于普通二维数组的操作:cout << "matrix[1][1] = " << matrix[1][1] << endl; // 输出 matrix 的第2行第2列元素
四、遍历二维
vector
方法一:使用双重循环
for(int i = 0; i < matrix.size(); i++) { for(int j = 0; j < matrix[i].size(); j++) { cout << matrix[i][j] << " "; } cout << endl; }
方法二:使用范围 for 循环(C++11及以上支持)
for(const auto& row : matrix) { for(const auto& elem : row) { cout << elem << " "; } cout << endl; }
五、修改元素
可以直接通过下标修改特定位置的元素:
matrix[0][0] = 100; // 修改第1行第1列的元素为100
六、添加行或列
由于
vector
是动态的,你可以随时向其添加新行或新列。添加一行
vector<int> newRow = {10, 20, 30}; matrix.push_back(newRow); // 向 matrix 添加一行
添加一列(稍微复杂一些)
由于
vector
的每行长度可能不同,因此添加列时需要对每一行都进行操作。for(auto& row : matrix) { row.push_back(40); // 向每一行末尾添加一个新元素40 }
七、删除行或列
删除一行
matrix.erase(matrix.begin() + 1); // 删除第2行
删除一列(同样需要逐行操作)
for(auto& row : matrix) { row.erase(row.begin() + 1); // 删除每一行的第2个元素 }
八、完整示例代码
以下是一个完整的例子,展示了如何定义、初始化、遍历、修改以及添加和删除元素:
#include <iostream> #include <vector> using namespace std; int main() { // 定义并初始化二维 vector vector<vector<int>> matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; // 遍历输出 cout << "原始矩阵:" << endl; for(const auto& row : matrix) { for(const auto& elem : row) { cout << elem << " "; } cout << endl; } // 修改元素 matrix[0][0] = 100; cout << "\n修改后的矩阵:" << endl; for(const auto& row : matrix) { for(const auto& elem : row) { cout << elem << " "; } cout << endl; } // 添加一行 vector<int> newRow = {10, 20, 30}; matrix.push_back(newRow); cout << "\n添加一行后的矩阵:" << endl; for(const auto& row : matrix) { for(const auto& elem : row) { cout << elem << " "; } cout << endl; } // 删除第二行 matrix.erase(matrix.begin() + 1); cout << "\n删除第二行后的矩阵:" << endl; for(const auto& row : matrix) { for(const auto& elem : row) { cout << elem << " "; } cout << endl; } return 0; }
这段代码演示了如何在C++中使用二维
vector
进行基本的操作,包括定义、初始化、遍历、修改、添加和删除元素。 - 指定行数和列数,所有元素初始化为默认值(如
- 1