#include <iostream>
// write your code here......
#include <vector>
using namespace std;
int main() {
// write your code here......
vector<int> vec;
int a;
while(cin>>a){
vec.push_back(a);
}
vector<int>::iterator iter=vec.begin();
for(; iter!=vec.end(); iter++){
cout<<*iter<<" ";
}
cout<<endl;
for(iter = vec.end()-1 ; iter>=vec.begin(); iter--){
cout<<*iter<<" ";
}
return 0;
}
C++ vector 超详细使用教程(零基础必看,最全常用用法+你的实战场景适配)
你之前手写过动态数组 int* a = new int[n],也学了类、多态,vector 就是用来彻底替代原生数组的「超级动态数组」,是C++ STL里最常用、最核心、必须吃透的容器,没有之一。vector 本质就是:C++官方帮你封装好的动态数组类,自动扩容、自动管理内存(不用写new/delete)、自带增删改查,所有原生数组能做的,vector都能做,还能做得更好,更安全。✅ 核心优势:不用手动管理内存、不会内存泄漏、不用写深拷贝、自动扩容,解决你手写数组的所有痛点!
✅ 一、vector 前置必备(写代码前必须加)
1. 必备头文件
所有 vector 的代码,第一行必须引入这个头文件,缺一不可:
#include <vector>
2. 命名空间(可选,但建议加)
不加的话,所有vector要写成std::vector,加了更简洁,你写代码一直加的,直接沿用即可:
using namespace std;
✅ 二、核心语法1:vector的「定义与初始化」(6种常用写法,够用100%场景)
语法格式:vector<存储的数据类型> 容器名;
vector<>里的内容是泛型/模板参数,指定vector要存什么类型的数据,int/char/string/自定义类/指针都可以!
最常用的6种初始化方式(按优先级排序,越靠前越常用)
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 写法1:定义空的vector,最常用!先创建空数组,后续再添加元素
vector<int> v1;
// 写法2:定义时直接初始化赋值(推荐,初始化已知数据)
vector<int> v2 = {1, 2, 3, 4, 5};
// 写法3:定义时指定数组长度,所有元素默认值为0
vector<int> v3(5); // v3 = {0,0,0,0,0}
// 写法4:定义时指定长度 + 指定初始化值
vector<int> v4(5, 10); // v4 = {10,10,10,10,10}
// 写法5:用一个vector初始化另一个vector(拷贝)
vector<int> v5(v2); // v5 = {1,2,3,4,5}
// 写法6:存储字符串类型(同理,存其他类型只需要改<>里的内容)
vector<string> v6 = {"hello", "vector", "STL"};
return 0;
}
✨ 关键提醒
vector<int> 里的 <int> 不能省略!这是模板的语法,告诉编译器这个数组存的是整数,存其他类型就换:
- 存浮点型:
vector<double> v; - 存字符型:
vector<char> v; - 存自定义类对象:
vector<Time> v;(比如你之前的Time类) - 存指针(多态必备):
vector<BaseCalculator*> v;(你的计算器多态)
✅ 三、核心语法2:vector 最常用的「增删改查」操作(重中之重,必会!)
这部分是vector的核心,80%的场景只用到下面这8个操作,全部都是成员函数,用 vector对象名.函数名() 调用,语法和你写的 类对象.成员函数() 完全一致!
所有例子都基于这个基础:
vector<int> v = {1,2,3,4,5};
👉 1. 尾部添加元素 【最常用TOP1】push_back(值)
给vector的最后面追加一个元素,vector会自动扩容(满了之后自动变大),不用你手动处理内存,完美替代你手写的数组扩容逻辑!
v.push_back(6); // v变成 {1,2,3,4,5,6}
v.push_back(7); // v变成 {1,2,3,4,5,6,7}
👉 2. 获取数组长度 【最常用TOP2】size()
返回vector里的元素个数,等价于你手写数组时的n,遍历数组必用,返回值是整数类型。
cout << v.size() << endl; // 输出5,因为v初始有5个元素 v.push_back(6); cout << v.size() << endl; // 输出6,添加后长度+1
👉 3. 访问指定下标元素 【最常用TOP3】v[下标]
和原生数组的访问方式完全一模一样!下标从0开始,支持读、写两种操作,这是你最熟悉的用法,无缝衔接!
// 读元素:获取下标0的元素
cout << v[0] << endl; // 输出1
// 写元素:修改下标2的元素值
v[2] = 30; // v变成 {1,2,30,4,5}
👉 4. 判断是否为空 empty()
判断vector里有没有元素,为空返回true,不为空返回false,防止遍历空数组报错。
vector<int> v_empty;
if(v_empty.empty()){
cout << "数组为空" << endl; // 会执行这句
}
👉 5. 清空所有元素 clear()
清空vector里的所有元素,清空后数组长度size()变为0,但不会释放内存(不影响后续使用)。
v.clear(); // v变成空数组 cout << v.size() << endl; // 输出0
👉 6. 尾部删除元素 pop_back()
删除vector最后面的一个元素,删除后长度size()减1。
v.pop_back(); // v变成 {1,2,3,4}
👉 7. 插入元素 insert(位置, 值) (偶尔用)
在指定下标位置插入一个元素,插入后后面的元素自动后移,vector自动扩容。
v.insert(v.begin()+1, 100); // 在下标1的位置插入100,v变成 {1,100,2,3,4,5}
👉 8. 删除元素 erase(位置) (偶尔用)
删除指定下标位置的元素,删除后后面的元素自动前移。
v.erase(v.begin()+2); // 删除下标2的元素,v变成 {1,2,4,5}
✅ 四、核心语法3:vector的「遍历方式」(3种,全部要会!)
遍历 = 把vector里的每个元素都访问一遍,vector有3种遍历方式,全部都要掌握,不同场景用不同方式,适配你的所有需求,全部基于你学过的知识,无缝衔接!
所有遍历例子都基于:
vector<int> v = {1,2,3,4,5};
✅ 方式1:数组式遍历 【最推荐、最常用】 for(int i=0; i<v.size(); i++)
和原生数组的遍历写法完全一模一样!你手写数组时怎么遍历,vector就怎么遍历,零基础零成本上手,这是你最先要掌握、最常用的方式!
// 遍历输出所有元素
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " "; // 用v[i]访问元素,和数组一样
}
// 输出:1 2 3 4 5
✅ 优势:语法熟悉、代码简洁、效率最高,90%的场景用这个就够了!
✅ 方式2:迭代器遍历 【STL标准写法】 vector<int>::iterator
迭代器你之前听过,核心记住一句话:迭代器 = vector专属的指针,语法和指针完全一致!
- 定义迭代器:
vector<int>::iterator it;(int换成你存储的类型) - 取元素:
*it(和指针*p完全一样) - 移动指针:
it++(下一个元素) - 开始位置:
v.begin()(数组第一个元素的地址) - 结束位置:
v.end()(数组最后一个元素的下一个地址,结束标志)
// 迭代器遍历
vector<int>::iterator it;
for (it = v.begin(); it != v.end(); it++) {
cout << *it << " "; // *it 访问迭代器指向的元素,和指针一样
}
// 输出:1 2 3 4 5
✅ 优势:STL标准写法,适配所有STL容器(vector/list/map),学会这个,其他容器的遍历也会了!
✅ 方式3:范围for遍历 【C++11简洁写法】 for(auto x : v)
C++11新增的语法,极简遍历,不用写下标、不用写迭代器,直接遍历所有元素,适合只需要读取元素,不需要下标的场景,代码量最少!
// 范围for遍历,auto自动推导类型为int
for (auto x : v) {
cout << x << " ";
}
// 输出:1 2 3 4 5
✅ 优势:代码极简,一行搞定遍历,适合快速写代码!
✅ 五、进阶用法1:vector 存储「自定义类对象」(适配你学的类/继承)
你之前写过 rectangle、cuboid、Time、Calculator 这些自定义类,vector可以直接存储这些类的对象,用法和存储int完全一样,没有任何区别!
例子:存储你之前的矩形类对象
#include <iostream>
#include <vector>
using namespace std;
class rectangle{
private:
int length,width;
public:
rectangle(int x=0,int y=0) : length(x), width(y) {}
int area(){ return length*width; }
};
int main() {
// 定义存储rectangle对象的vector
vector<rectangle> rectVec;
// 添加对象到vector
rectVec.push_back(rectangle(2,3));
rectVec.push_back(rectangle(4,5));
// 遍历调用成员函数
for(int i=0; i<rectVec.size(); i++){
cout << rectVec[i].area() << endl; // 输出6、20
}
return 0;
}
✅ 六、进阶用法2:vector 存储「指针」实现【多态】(你的核心实战场景,必看!)
这个是对你最有用的用法,完美适配你之前写的「计算器多态代码」!你之前写多态是用 BaseCalculator* cal = new AddCalculator; 手动new/delete,容易忘记释放内存,而用vector存储父类指针,可以统一管理所有子类对象,完美实现多态+自动管理对象,这是C++开发中最标准的多态写法,你必须吃透!
✨ 完整实战代码(你的计算器多态+vector,企业级标准写法)
#include <iostream>
#include <vector>
using namespace std;
// 父类:计算器基类
class BaseCalculator {
public:
int m_A;
int m_B;
virtual int getResult(){ return 0; }
virtual ~BaseCalculator() {} // 虚析构必须加,防止内存泄漏
};
// 加法子类
class AddCalculator : public BaseCalculator {
public:
int getResult() override { return m_A + m_B; }
};
// 减法子类
class SubCalculator : public BaseCalculator {
public:
int getResult() override { return m_A - m_B; }
};
int main() {
// 核心:定义vector存储【父类指针】
vector<BaseCalculator*> calVec;
// 往vector里添加子类对象的地址(多态核心:父类指针指向子类对象)
calVec.push_back(new AddCalculator);
calVec.push_back(new SubCalculator);
// 遍历vector,调用多态函数 → 完美实现多态!
for(int i=0; i<calVec.size(); i++){
calVec[i]->m_A = 10;
calVec[i]->m_B = 5;
cout << calVec[i]->getResult() << endl; // 输出 15 5
}
// 最后统一释放内存(避免内存泄漏)
for(int i=0; i<calVec.size(); i++){
delete calVec[i];
}
return 0;
}
✅ 这个写法的好处:新增乘法/除法计算器时,只需要加一个子类,然后calVec.push_back(new MulCalculator)即可,原有代码一行不改,完美体现多态的扩展性!
✅ 七、vector 对比 原生动态数组(为什么vector香?)
你之前手写的动态数组:int* a = new int[n];,对比vector,vector的优势是碾压级的,这也是为什么一定要用vector的原因:
内存管理 | 手动写
,容易泄漏/崩溃 | 自动管理,无需手动操作 |
扩容 | 手动重新分配内存+拷贝数据,超麻烦 | 自动扩容,
直接加元素 |
深拷贝 | 必须自己写深拷贝构造,容易出错 | 自带深拷贝,赋值/拷贝都安全 |
越界检查 | 无,越界直接崩溃 | 有间接保护,更安全 |
代码量 | 多,需要写构造/析构/深拷贝 | 极少,一行定义,直接用 |
✨ 结论:以后再也不要手写动态数组了,所有数组场景都用vector替代!
✅ 八、易错点提醒(新手必避坑)
- 下标越界:vector的下标从0开始,最大下标是
v.size()-1,如果访问v[v.size()]会直接崩溃,和数组一样; - 空vector访问元素:如果
v.empty()为true,还访问v[0]会崩溃; - 存储指针时记得释放内存:比如存储多态指针的vector,最后一定要遍历delete,否则内存泄漏;
- vector的size()返回值是无符号整数:不要写
for(int i=v.size()-1; i>=0; i--),会出现死循环,用int len = v.size();先存起来即可。
✅ 九、vector 常用操作速查表(收藏备查,不用记,看表就行)
vector<int> v; // 定义空vector v.push_back(x); // 尾部加元素 v.size(); // 获取长度 v[i]; // 访问下标i的元素 v.empty(); // 判断是否为空 v.clear(); // 清空所有元素 v.pop_back(); // 尾部删元素 v.insert(v.begin()+i,x);// 下标i插入x v.erase(v.begin()+i); // 删除下标i的元素
✅ 总结(核心知识点,一句话记死)
- vector 是「动态数组」,完全替代原生数组,自动管理内存、自动扩容、无需new/delete;
- 核心语法:
vector<类型> 名定义,push_back加元素,size()取长度,v[i]访问元素; - 遍历方式:数组式遍历(最常用)、迭代器遍历(标准)、范围for(简洁);
- 高阶用法:存储自定义类对象、存储父类指针实现多态(你的核心场景);
- 记住:以后写C++,所有需要数组的地方,无脑用vector就对了!
你现在的基础(类、指针、多态)已经完全能吃透vector了,vector是你STL的入门第一课,学会它之后,你会发现C++编程的效率直接翻倍,再也不用被内存管理的问题困扰了!🎉

京公网安备 11010502036488号