当前位置: 首页 > news >正文

C++入门自学Day8-- 初识Vector

往期内容回顾

          String类的自实现

         String类的使用(续)  

         String类(续)

         String类(初识)


C++ Vector 全面解析:从 C 数组到现代动态容器

前言

        在 C 语言中,数组是最常见的顺序存储结构,但它存在固定长度、不能自动扩容、缺少边界检查等缺点。C++ 标准库引入了 std::vector 动态数组容器,为我们提供了更安全、更灵活的顺序存储解决方案。

        本文将从 C 语言数组的局限性出发,深入解析 C++ vector 的设计理念、用法和底层原理,并结合实例对比二者的异同,帮助你从“旧世界”平滑过渡到“现代 C++”。


一、C++ 中的 vector 容器介绍

1. 什么是 vector?

        vector 是 C++ 标准库(STL)中提供的一个序列容器,属于动态数组。它能够在运行时动态地管理存储空间,支持自动扩容,能方便地存储和操作一组同类型的元素。

简单来说,vector 就像一个动态大小的数组,使用起来非常灵活。


2. 为什么使用 vector?

  • 动态大小:普通数组大小固定,不能改变;vector 可以根据需要自动增长或缩小。

  • 随机访问:支持像数组一样通过索引快速访问元素,时间复杂度为 O(1)。

  • 丰富的接口:提供了插入、删除、排序、遍历等常用操作。

  • 安全性高:相比裸数组,vector 自动管理内存,避免了很多内存泄漏和越界问题。

  • 与算法库兼容:可以方便地与 STL 其他算法和容器配合使用。


3. vector 的基本用法示例

#include <iostream>
#include <vector>int main() {// 创建一个空的int类型vectorstd::vector<int> v;// 添加元素v.push_back(10);v.push_back(20);v.push_back(30);// 访问元素for (size_t i = 0; i < v.size(); ++i) {std::cout << v[i] << " ";}std::cout << std::endl;// 使用范围for循环for (auto elem : v) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}


4. vector 的常用成员函数

函数

作用

push_back(value)

在末尾添加元素

pop_back()

删除末尾元素

size()

返回当前元素个数

empty()

判断是否为空

clear()

清空所有元素

operator[]

通过索引访问元素(不做越界检查)

at(index)

通过索引访问元素(做越界检查)

front()

返回第一个元素

back()

返回最后一个元素

insert(pos, value)

在指定位置插入元素

erase(pos)

删除指定位置的元素

resize(n)

改变容器大小

reserve(n)

预留空间,减少扩容次数

capacity()

当前分配的空间大小


二、常用函数接口详解

1. 构造与初始化

#include <vector>
#include <iostream>
using namespace std;int main() {vector<int> v1;               // 空 vectorvector<int> v2(5);            // 5 个默认值(0)vector<int> v3(5, 42);        // 5 个 42vector<int> v4 = {1, 2, 3};   // 列表初始化vector<int> v5(v4);           // 拷贝构造
}

2. 容量相关函数

v.size();      // 当前元素个数
v.capacity();  // 已分配的容量
v.empty();     // 是否为空
v.reserve(100); // 预留容量(减少扩容次数)
v.resize(10);   // 改变元素个数,多余的补默认值// 查看容量的变化
void test5(){vector<int> v1;v1.assign({1,2,3,4,5,6,7,8,9});// int arr[] = {1,2,3,4,5,6,7,8,9};for(int i =10;i<100;i++){v1.push_back(i);if (i%10 == 0){cout<< v1.capacity()<<endl;}}
}int main(){// test1();test5();
}

3. 元素访问

v[0];        // 不做边界检查
v.at(0);     // 有边界检查,越界会抛出异常
v.front();   // 第一个元素
v.back();    // 最后一个元素
v.data();    // 返回底层数组指针

4. 修改操作

v.push_back(10);       // 末尾添加
v.pop_back();          // 删除末尾
v.insert(v.begin()+1, 20); // 插入
v.erase(v.begin()+2);  // 删除单个元素
v.clear();             // 清空void test5(){vector<int> v1;v1.assign({1,2,3,4,5,6,7,8,9});v1.insert(v1.begin(),10);v1.insert(v1.begin()+3,20);for(auto num:v1){cout<< num<<" ";}cout<<endl;v1.erase(v1.begin());v1.erase(v1.end()-1);
//v1.end() 指向的是容器末尾的“下一个位置”,不指向任何有效元素for(auto num:v1){cout<< num<<" ";}cout<<endl;
}int main(){// test1();test5();
}

输出描述:

10 1 2 20 3 4 5 6 7 8 9 
1 2 20 3 4 5 6 7 8 


5. 迭代器遍历

for (size_t i = 0; i < v.size(); ++i) cout << v[i] << " ";
for (auto it = v.begin(); it != v.end(); ++it) cout << *it << " ";
for (auto &x : v) cout << x << " "; // C++11 范围 forvoid test1(){vector<int> v1;v1.assign({1,2,3,4,5,6,7,8,9});//遍历修改数据for(int i = 0;i<v1.size();i++){cout<< v1[i]<<" ";}cout<<endl;/// for(auto num :v1){cout<< num<<" ";}cout<<endl;///vector<int>::iterator it ;for(it = v1.begin();it<v1.end(); it++){cout<<*it<<" ";}cout<<endl;
}

注意:const iterator的用法

void Print_Vector(const vector<int>& v){vector<int>::const_iterator it = v.begin();while (it != v.end()){(*it) += 1;cout<< *it<<" ";it++;}cout<<endl; 
}
void test3(){vector<int> v1;v1.assign({1,2,3,4,5,6,7,8,9});Print_Vector(v1);
}

const iterator无法进行元素的修改

反向迭代器:reverse_iterator
 

void test4(){//const 迭代器无法修改内容vector<int> v1;v1.assign({1,2,3,4,5,6,7,8,9});vector<int>::reverse_iterator it = v1.rbegin();while (it != v1.rend()){cout<< *it<<" ";it++;}cout<<endl;     
}int main(){// test1();test4();
}

输出:

9 8 7 6 5 4 3 2 1 


三、Vector 的底层原理

  1. 存储结构

    内部维护一个连续内存区 + size(元素数量)+ capacity(已分配容量)。

  2. 扩容机制

    当 size == capacity 时,分配更大的内存(通常 1.5~2 倍),拷贝旧数据,再释放旧内存。

  3. 时间复杂度

    • 随机访问:O(1)

    • 尾部插入/删除:均摊 O(1)

    • 中间插入/删除:O(n)

  4. 异常安全

    扩容时可能抛出异常(内存分配失败),但保证不泄漏资源。


四、与算法库的联动

        注意我们可以发现其实vector的库中并没有提供find函数--查找指定元素的位置,但是在<algorithm>头文件中提供了find函数模版接口。

​void test6(){vector<int> v1;v1.assign({1,2,3,4,5,6,7,8,9});vector<int>::iterator pos = find(v1.begin(),v1.end(),5);for(auto num:v1){cout<<num<<" ";}cout<<endl;
}int main(){// test1();test6();
}

输出描述:

1 2 3 4 5 6 7 8 9 

那么这里的find函数是如何实现的呢?-->利用函数模版进行实现的

template<class Inputiterator, class T>
Inputiterator find(Inputiterator begin, Inputiterator end, T val){while (begin!=end){   if(*begin == val){return begin;}begin++;}}

这里的class Inputiterator指的就是我们的迭代器(指针),class T 就是寻找的变量类型。


五、与 C 数组的互操作

#include <vector>
#include <cstring>
using namespace std;int main() {vector<int> v = {1, 2, 3};int *arr = v.data();  // 获取 C 风格指针memcpy(arr, arr+1, sizeof(int) * 2); // C API 操作
}

六. 总结

        vector 是 C++ 最常用的序列容器,灵活且高效。它结合了数组的快速访问和动态管理内存的优势,适合绝大多数存储需求。熟练掌握 vector,能够极大提高 C++ 编程的效率和代码质量。

http://www.dtcms.com/a/324257.html

相关文章:

  • leetcode2379:得到K个黑块的最少涂色次数(定长滑动窗口)
  • 2.变量和常量
  • Go 工具链环境变量实战:从“command not found”到工具全局可用的全流程复盘
  • 【数据结构入门】栈和队列的OJ题
  • 二维前缀和问题
  • MySQL面试题及详细答案 155道(041-060)
  • 构建第三方软件仓库
  • 数据类型取值范围
  • String AOP、事务、缓存
  • 【18】OpenCV C++实战篇——【项目实战】OpenCV C++ 精准定位“十字刻度尺”中心坐标,过滤图片中的干扰,精准获取十字交点坐标
  • 力扣559:N叉树的最大深度
  • XGBoost算法在机器学习中的实现
  • C语言:指针(2)
  • Gin vs Beego vs Echo:三大主流 Go Web 框架深度对比
  • 前端开发中的常见问题与实战解决方案​
  • JS数组排序算法
  • scanpy单细胞转录组python教程(三):单样本数据分析之数据标准化、特征选择、细胞周期计算、回归等
  • 2025.8.10总结
  • 学生成绩管理系统的 SQL 表设计与多表查询实战
  • 部署一个免费开源的博客系统
  • 库的制作和原理
  • 双亲委派机制是什么?
  • 大模型工具集成四层架构:识别、协议、执行与实现
  • reinterpret_cast and static cast
  • Lua的数组、迭代器、table、模块
  • Elasticsearch 搜索模板(Search Templates)把“可配置查询”装进 Mustache
  • 从MySQL到大数据平台:基于Spark的离线分析实战指南
  • 重学React(四):状态管理二
  • Spark执行计划与UI分析
  • 【软考中级网络工程师】知识点之 DCC 深度剖析