【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中的元素

intmain(){// 初始化一个 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 异常(可捕获处理);效率略低于 []

intmain(){// 初始化一个 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开始)
特点:直接内存访问,执行效率最佳;但不进行边界检查,越界访问可能引发未定义行为(程序崩溃或内存污染)[] 下标运算符(最常用,效率最高)

intmain(){// 初始化一个 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. 普通迭代器(读写)intmain(){// 初始化一个 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;}return0;}
2.3.2 常性迭代器

(只可读元素但是不可以修改值)

intmain(){// 初始化一个 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;return0;}
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_;};intmain(){ vector<Person> v;// push_back:先构造临时Person,再移动到vector v.push_back(Person("Alice",20));// emplace_back:直接在vector尾部原地构造Person v.emplace_back("Bob",22);return0;}

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

特殊情况

  • 内存变化:
    • 自动扩容(当新元素数量 > 当前 capacity)
    • 不会主动缩容(如原 capacity=10,assign(2, 0) 后 capacity 仍为 10)
  • 元素析构:
    • 对于类对象,assign() 会先调用所有原有元素的析构函数,再构造新元素,避免内存泄漏assign() 是 vector 的成员函数,作用是替换容器中所有现有元素(先清空原元素,再插入新元素),会直接改变 size,也可能间接改变 capacity(如果新元素数量超过当前容量)。

n=0 时:assign(0, val) 等价于清空 vector(size=0),但 capacity 不变(需使用 shrink_to_fit() 释放内存)

vec.assign(0,0);// 清空所有元素,size=0,capacity不变

6.迭代器失效

6.1迭代器失效本质

迭代器本质是 “容器元素的内存指针 / 索引封装”,当容器底层内存布局改变(如扩容、元素移动)、元素被删除时,迭代器指向的地址 / 逻辑位置失效,此时解引用或操作迭代器会导致 UB(未定义行为)。

6.2迭代器失效场景

在这里插入图片描述

Read more

Flutter 三方库 tflite_web 端云协同 AI 引擎鸿蒙化高配适配:搭建异构计算 WebGL 后台管线并强力驱动 TensorFlow Lite-适配鸿蒙 HarmonyOS ohos

Flutter 三方库 tflite_web 端云协同 AI 引擎鸿蒙化高配适配:搭建异构计算 WebGL 后台管线并强力驱动 TensorFlow Lite-适配鸿蒙 HarmonyOS ohos

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 tflite_web 端云协同 AI 引擎鸿蒙化高配适配:搭建异构计算 WebGL 后台管线并强力驱动 TensorFlow Lite 轻量大模型推理内核运转 前言 在 OpenHarmony 构建混合架构(Hybrid App)的过程中,将 AI 能力直接下沉到客户端侧执行已成为主流趋势。虽然鸿蒙原生提供了强大的 AI 框架,但对于已有大量积累、且运行在 Flutter Web 容器中的应用而言,寻找一致性的端侧 AI 推理方案至关重要。tflite_web 库为基于 Flutter Web 的应用提供了调用 TensorFlow Lite 模型的能力。本文将调研其在鸿蒙 Web

By Ne0inhk
全栈分页方案:MyBatisPlus后端与Thymeleaf前端深度整合指南

全栈分页方案:MyBatisPlus后端与Thymeleaf前端深度整合指南

目录 前言 一、MybatisPlus搭建及表介绍 1、MybatisPlus环境搭建 2、示例表结构介绍 二、Java后台分页实现 1、实体类实现 2、业务层分页实现 3、控制层实现 三、Thymeleaf分页集成 1、分页表格展示 2、分页条集成 3、成果展示 四、可能遇到的问题 1、分页不展示 2、问题解决 五、总结 前言         在当今的软件开发中,分页功能是提升用户体验和系统性能的关键。无论是企业级应用还是面向用户的平台,高效分页都能显著改善交互体验。今天将带你深入了解如何通过 MyBatisPlus 和 Thymeleaf 的深度整合,打造一个完整的全栈分页解决方案。分页功能不仅能够提升用户交互的流畅性,还能显著降低服务器的负载,提高系统的整体性能。将 MyBatisPlus 和 Thymeleaf

By Ne0inhk
『AI辅助Skill』掌握三大AI设计Skill:前端独立完成产品设计全流程

『AI辅助Skill』掌握三大AI设计Skill:前端独立完成产品设计全流程

📣读完这篇文章里你能收获到 1. 🎨 掌握ASCII Design快速验证产品想法的方法 2. 🖼️ 学会Wireframe Design生成专业SVG线稿 3. 💻 了解三种Frontend Design Skills的选择策略 4. 🚀 掌握完整OPC工作流,1-2天完成产品开发 文章目录 * 前言 * 一、三大AI设计Skill工作流 * 1.1 传统流程的核心痛点 * 1.2 AI辅助工作流 * 二、ASCII与Wireframe设计技能 * 2.1 ASCII Design Skill —— 秒级验证产品想法 * 2.2 Wireframe Design Skill —— 专业级设计原型 * ASCII vs SVG:如何选择 * 核心特性 * 工作流程 * 三、Frontend Design Skills选择策略 * 3.1

By Ne0inhk
【AI赋能】MCP+Skill能力下的前端JS逆向自动化落地(附工具)

【AI赋能】MCP+Skill能力下的前端JS逆向自动化落地(附工具)

项目地址 https://github.com/Fausto-404/js-reverse-automation--skill js-reverse-automation--skill 结合chrome-devtools-mcp的能力并加上Skill的规范,实现JSRPC+Flask+autoDecoder方案的前端JS逆向自动化分析,提升JS逆向的效率 适用场景 * 需要快速落地前端签名/加密参数逆向 * 需要将js逆向逻辑封装为可复用的代码 * 需要与 Burp 配合进行抓包、改包 流程设计思路 针对js逆向中常用的远程调用法进行js逆向(如JSRPC+Mitmproxy、JSRPC+Flask等)中,初始配置阶段中面对的定位加密函数、编写注册代码、编写python代码等繁琐操作,通过引入AI的MCP和Skill技术进行赋能,让AI自动完成函数发现与注册代码生成,最终实现从“半自动”到“高自动”的跨越,人员全程只需下方指令,并最终配置一下burp即可完成JS逆向的全流程。 核心能力 * 基于 MCP 连接真实浏览器,触发并跟踪js加密/签名链路

By Ne0inhk