网站建设策划框架高创园网站建设方案

张小明 2026/1/2 22:51:58
网站建设策划框架,高创园网站建设方案,网页设计的代码,营销云产品#x1f525;铅笔小新z#xff1a;个人主页 #x1f3ac;博客专栏#xff1a;C学习 #x1f4ab;滴水不绝#xff0c;可穿石#xff1b;步履不休#xff0c;能至渊。 引言 在C标准模板库#xff08;STL#xff09;中#xff0c;vector是最重要、最常用的容器之一…铅笔小新z个人主页博客专栏C学习滴水不绝可穿石步履不休能至渊。引言在C标准模板库STL中vector是最重要、最常用的容器之一。它提供了动态数组的功能能够自动管理内存同时保持了数组的随机访问特性。本文将深入探讨vector的各个方面从基本使用到高级特性再到底层实现原理。1. vector的基本介绍1.1 vector是什么vector是一个序列容器表示可以改变大小的数组。与普通数组不同vector能够动态增长和收缩自动处理内存管理。它支持快速随机访问在尾部插入和删除元素效率高但在中间或头部插入删除效率相对较低。1.2 学习vector的三个境界能用掌握基本接口能够在实际编程中使用vector明理理解vector的工作原理和内部机制能扩展能够根据需要自定义或扩展vector的功能1.3vector 相关接口2. vector的基本使用2.1 vector的构造函数// 1. 默认构造函数 - 创建空vectorvectorintv1;// 2. 构造并初始化n个valvectorintv2(5,10);// 5个元素每个都是10// 3. 拷贝构造vectorintv3(v2);// 4. 使用迭代器范围构造intarr[]{1,2,3,4,5};vectorintv4(arr,arr5);2.1.1 默认构造函数vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr){}2.1.2 构造并初始化n个valvector(size_t n,constTvalT()){reserve(n);for(size_t i0;in;i){push_back(val);}}2.1.3 拷贝构造vector(constvectorTv){reserve(v.size());for(autoe:v){push_back(e);}}2.2 vector的迭代器迭代器提供了访问容器元素的统一方式vectorintv{1,2,3,4,5};// 正向迭代器for(autoitv.begin();it!v.end();it){cout*it ;}// 反向迭代器for(autoritv.rbegin();rit!v.rend();rit){cout*rit ;}// 范围for循环C11for(autoelem:v){coutelem ;}2.3 vector的空间管理vector有两个重要的容量概念size: 当前容器中实际元素的数量capacity: 容器在不重新分配内存的情况下可以容纳的元素数量vectorintv;coutsize: v.size()endl;// 0coutcapacity: v.capacity()endl;// 0coutempty: v.empty()endl;// truev.reserve(100);// 预分配100个元素的空间coutcapacity after reserve: v.capacity()endl;// 100v.resize(50);// 改变size为50多出的位置用0填充coutsize after resize: v.size()endl;// 502.4 vector的容量增长策略vector的容量增长策略在不同实现中有所不同voidTestVectorExpand(){vectorintv;size_t szv.capacity();coutcapacity growth:\n;for(inti0;i100;i){v.push_back(i);if(sz!v.capacity()){szv.capacity();coutcapacity changed: szendl;}}}不同编译器的实现差异VS系列编译器按大约1.5倍增长g编译器按2倍增长这种差异是因为不同版本的STL实现不同不要固化认为vector总是2倍增长。2.5 vector的增删查改操作vectorintv{1,2,3};// 1. 添加元素v.push_back(4);// 尾部插入v.insert(v.begin()1,5);// 在指定位置插入// 2. 删除元素v.pop_back();// 尾部删除v.erase(v.begin());// 删除指定位置元素v.clear();// 清空所有元素// 3. 访问元素coutv[0]endl;// 使用operator[]不检查边界coutv.at(0)endl;// 使用at()会检查边界// 4. 查找元素需要包含algorithmautoitfind(v.begin(),v.end(),3);if(it!v.end()){coutFound: *itendl;}// 5. 交换两个vectorvectorintv2{10,20,30};v.swap(v2);// 交换v和v2的内容3. vector迭代器失效问题重点迭代器失效是使用vector时需要特别注意的问题。迭代器失效意味着迭代器指向的内存空间已经无效继续使用会导致未定义行为通常程序崩溃。3.1 vector的底层存储结构vector在内存中是一段连续的存储空间templateclassTclassvector{private:T*_start;// 指向数据起始位置T*_finish;// 指向最后一个元素的下一个位置T*_end_of_storage;// 指向存储空间末尾// ...};当你获取一个迭代器时它本质上是一个指针或指针的封装vectorintv{1,2,3,4,5};autoitv.begin();// it本质上是一个 int*指向第一个元素内存布局如下地址0x1000 0x1004 0x1008 0x100C 0x1010 0x1014... 数据 1 2 3 4 5 ... ↑ it (指向0x1000)3.2 导致迭代器失效的操作情况1空间重新分配vectorintv{1,2,3,4,5};autoitv.begin();// 以下操作都可能导致迭代器失效v.resize(100);// 扩容v.reserve(100);// 扩容v.push_back(6);// 可能导致扩容v.insert(v.begin(),0);// 可能导致扩容v.assign(100,8);// 重新赋值可能改变容量// 错误it可能已经失效while(it!v.end()){// 可能访问已释放的内存cout*it ;it;}扩容过程在堆上申请新的、更大的连续内存空间将旧内存中的数据拷贝到新内存释放旧内存空间更新vector的内部指针到新内存关键问题迭代器it仍然指向旧的、已被释放的内存地址旧内存已被释放0x1000 0x1004 0x1008... ↑ it (仍然指向这里但内存已无效) 新内存当前有效0x2000 0x2004 0x2008... 1 2 3 ...解决方案在可能导致扩容的操作后重新获取迭代器。情况2元素删除vectorintv{1,2,3,4,5};autoitv.begin()2;// it指向元素3v.erase(v.begin()1);// 删除元素2删除过程删除前 [1, 2, 3, 4, 5] ↑ it指向3 删除元素2 1. 删除位置1的元素 [1, _, 3, 4, 5] 2. 向前移动元素3-5 [1, 3, 4, 5] 删除后 [1, 3, 4, 5] ↑ it指向4不是原来的3了解决方案使用erase的返回值更新迭代器。// 正确删除vector中所有偶数的示例vectorintv{1,2,3,4};autoitv.begin();while(it!v.end()){if(*it%20){itv.erase(it);// erase返回下一个有效迭代器}else{it;}}情况3插入元素导致内存移动即使不扩容插入操作也可能导致迭代器失效vectorintv{1,2,3,4,5};autoitv.begin()2;// it指向元素3v.insert(v.begin()1,99);// 在位置1插入99插入操作需要移动元素插入前 [1, 2, 3, 4, 5] ↑ it指向3 插入过程 1. 向后移动元素2-5 [1, _, 2, 3, 4, 5] 2. 在位置1插入99 [1, 99, 2, 3, 4, 5] 插入后 [1, 99, 2, 3, 4, 5] ↑ it仍然指向原来的内存位置但现在是元素2虽然it指向的内存地址仍然有效但元素已经改变了位置原来的迭代器不再指向期望的元素。情况4编译器的差异处理不同编译器对迭代器失效的处理严格程度不同VS编译器检测严格失效后立即报错g编译器检测较宽松可能继续运行但结果错误// 在g下可能不崩溃但结果错误vectorintv{1,2,3,4,5};autoitv.begin();v.reserve(100);// 扩容迭代器失效// 可能不崩溃但输出错误while(it!v.end()){cout*it ;// 未定义行为it;}3.3 string的迭代器失效问题与vector类似string也有迭代器失效问题string shello;autoits.begin();s.resize(20,!);// 可能导致扩容迭代器失效// 错误使用可能已失效的迭代器while(it!s.end()){cout*it;// 可能崩溃it;}3.4 具体操作分析(1)resize(n, val)可能扩容vectorintv{1,2,3,4,5};// 容量5autoitv.begin();v.resize(100,0);// 需要扩容到至少100// 旧内存不够 → 申请新内存 → 拷贝数据 → 释放旧内存// it失效(2)reserve(n)可能扩容vectorintv{1,2,3,4,5};// 容量5autoitv.begin();v.reserve(100);// 容量从5扩大到100// 必须重新分配内存 → it失效(3)push_back(val)可能触发扩容vectorintv{1,2,3,4,5};// 容量5已满autoitv.begin();v.push_back(6);// 需要扩容// 容量不足 → 重新分配内存 → it失效(4)insert(pos, val)可能触发扩容或移动vectorintv{1,2,3,4,5};// 容量5autoitv.begin()2;v.insert(v.begin(),0);// 在开头插入// 两种情况// 1. 如果容量不足扩容 → it完全失效指向释放的内存// 2. 如果容量足够元素向后移动 → it指向的元素改变(5)assign(n, val)完全重新分配vectorintv{1,2,3,4,5};autoitv.begin();v.assign(100,8);// 替换所有内容// 清空现有元素 → 可能需要重新分配内存 → it失效3.5 为什么访问失效迭代器会导致问题对于已释放的内存情况1vectorintv{1,2,3};autoitv.begin();v.reserve(100);// 重新分配内存释放旧内存cout*it;// 访问已释放的内存可能的后果程序崩溃访问无效内存地址段错误读取垃圾值内存已被其他数据覆盖未定义行为任何事情都可能发生对于元素位置改变情况2和3vectorintv{1,2,3};autoitv.begin()1;// 指向2v.insert(v.begin(),0);// 插入元素cout*it;// 输出2不可能是其他值结果是逻辑错误迭代器不指向期望的元素。3.6 正确的做法方案1重新获取迭代器vectorintv{1,2,3,4,5};autoitv.begin();// 执行可能使迭代器失效的操作v.resize(100);// 重新获取迭代器itv.begin();// 重要重新赋值// 现在可以安全使用while(it!v.end()){cout*it ;it;}方案2使用索引替代迭代器vectorintv{1,2,3,4,5};size_t index0;// 使用索引而不是迭代器v.resize(100);// 扩容// 索引不受影响只要不超过sizeif(indexv.size()){coutv[index];// 安全}方案3使用返回值更新迭代器vectorintv{1,2,3,4,5};autoitv.begin();// insert返回新插入元素的位置itv.insert(it,0);// 在开头插入0it更新为指向新元素// erase返回被删除元素的下一个位置itv.erase(it);// 删除it指向的元素it更新为下一个元素3.7 总结迭代器失效的核心原因操作失效原因影响范围resize/reserve内存重新分配所有迭代器、指针、引用失效push_back可能触发内存重新分配如果扩容所有迭代器失效insert1. 可能扩容 2. 元素移动1. 所有迭代器失效 2. 部分迭代器指向错误元素erase元素向前移动被删除及之后位置的迭代器失效assign/clear完全重新分配或清空所有迭代器失效根本原因vector保证元素在内存中连续存储。为了维持这种连续性当需要更多空间或插入删除元素时必须移动元素或重新分配内存这会导致原有的地址引用失效。重要原则在修改vector容量的操作后永远假设所有现有的迭代器、指针和引用都已失效除非操作文档明确说明它们保持有效。4. vector在算法题中的应用4.1只出现一次的数字classSolution{public:intsingleNumber(vectorintnums){intresult0;for(intnum:nums){result^num;// 利用异或性质}returnresult;}};4.2杨辉三角classSolution{public:vectorvectorintgenerate(intnumRows){vectorvectorinttriangle(numRows);for(inti0;inumRows;i){triangle[i].resize(i1,1);// 每行有i1个元素初始化为1// 计算中间元素for(intj1;ji;j){triangle[i][j]triangle[i-1][j-1]triangle[i-1][j];}}returntriangle;}};4.3删除排序数组中的重复项classSolution{public:intremoveDuplicates(vectorintnums){if(nums.empty())return0;intk0;for(inti1;inums.size();i){if(nums[i]!nums[k]){nums[k]nums[i];}}returnk1;}};5. vector的模拟实现5.1 vector的基本框架namespacemy{templateclassTclassvector{private:T*_start;// 指向数据起始位置T*_finish;// 指向最后一个元素的下一个位置T*_end_of_storage;// 指向存储空间末尾public:// 构造函数vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr){}// 析构函数~vector(){delete[]_start;_start_finish_end_of_storagenullptr;}// 容量相关size_tsize()const{return_finish-_start;}size_tcapacity()const{return_end_of_storage-_start;}boolempty()const{return_start_finish;}// 元素访问Toperator[](size_t pos){return_start[pos];}constToperator[](size_t pos)const{return_start[pos];}// 迭代器T*begin(){return_start;}T*end(){return_finish;}constT*begin()const{return_start;}constT*end()const{return_finish;}// 预留空间voidreserve(size_t n){if(ncapacity()){T*new_startnewT[n];size_t szsize();// 深拷贝元素for(size_t i0;isz;i){new_start[i]_start[i];}delete[]_start;_startnew_start;_finish_startsz;_end_of_storage_startn;}}// 添加元素voidpush_back(constTval){if(_finish_end_of_storage){reserve(capacity()0?4:capacity()*2);}*_finishval;_finish;}// 交换数据voidswap(vectorTv){std::swap(_start,v._start);std::swap(_finish,v._finish);std::swap(_end_of_storage,v._end_of_storage);}// 赋值运算符重载vectorToperator(vectorTv){swap(v);return*this;}// 插入数据iteratorinsert(iterator pos,constTx){assert(pos_start);assert(pos_finish);// 扩容if(_finish_end_of_storage){size_t lenpos-_start;reserve(capacity()0?4:capacity()*2);pos_startlen;}iterator end_finish-1;while(endpos){*(end1)*end;--end;}*posx;_finish;returnpos;}// 删除数据iterarorerase(iterator pos){assert(pos_start);assert(pos_finish);iterator itpos1;while(it!end()){*(it-1)*it;it;}--_finish;returnpos;}};}5.2 使用memcpy的问题在实现vector的扩容时不能简单地使用memcpy进行内存拷贝// 错误示例使用memcpy拷贝自定义类型voidreserve(size_t n){if(ncapacity()){T*new_startnewT[n];// 错误对于管理资源的自定义类型memcpy是浅拷贝memcpy(new_start,_start,size()*sizeof(T));delete[]_start;// 释放旧空间可能导致资源重复释放_startnew_start;// ... 其他更新}}问题分析memcpy是二进制内存拷贝执行的是浅拷贝对于管理资源的自定义类型如string浅拷贝会导致多个对象共享同一资源释放旧空间时资源被释放新空间中的对象指向已释放的资源正确做法使用深拷贝// 正确做法使用深拷贝voidreserve(size_t n){if(ncapacity()){T*new_startnewT[n];size_t szsize();// 深拷贝调用元素的拷贝构造函数或赋值运算符for(size_t i0;isz;i){new_start[i]_start[i];// 调用T的赋值运算符或拷贝构造函数}// 析构旧元素for(size_t i0;isz;i){_start[i].~T();// 显式调用析构函数}delete[]_start;_startnew_start;_finish_startsz;_end_of_storage_startn;}}6. 动态二维数组的实现vector可以方便地实现动态二维数组// 创建n行的二维数组vectorvectorintcreateMatrix(intn){vectorvectorintmatrix(n);for(inti0;in;i){matrix[i].resize(i1,1);// 第i行有i1个元素}returnmatrix;}// 访问二维数组voidprintMatrix(constvectorvectorintmatrix){for(inti0;imatrix.size();i){for(intj0;jmatrix[i].size();j){coutmatrix[i][j] ;}coutendl;}}7. 使用vector的最佳实践预分配空间如果知道大概需要多少元素使用reserve()预分配空间避免频繁扩容。谨慎使用迭代器在可能修改容量的操作后不要使用旧的迭代器。选择合适的访问方式随机访问使用operator[]或at()遍历使用范围for循环或迭代器性能敏感考虑使用指针访问注意元素的拷贝成本存储大对象时考虑存储指针或使用移动语义。善用swap使用swap()快速清空vector或交换两个vector的内容。// 快速清空vector释放内存vectorintv(1000000);vectorint().swap(v);// 清空v并释放内存// C11更简洁的方式v.clear();v.shrink_to_fit();// 请求释放未使用的内存总结vector是C中最重要、最常用的容器之一。掌握vector不仅需要了解其基本用法还需要深入理解其内部工作原理特别是迭代器失效、内存管理和性能特征。通过合理使用vector可以编写出高效、安全的C代码。在实际开发中应根据具体需求选择合适的容器。vector适合需要频繁随机访问、尾部插入删除的场景。如果需要频繁在中间插入删除可能需要考虑list或deque如果需要快速查找可能需要考虑set或map。通过深入理解vector我们不仅能够更好地使用这个容器还能够学习到C内存管理、模板编程、异常安全等高级主题为成为更优秀的C程序员打下坚实基础。希望这篇长文对你有帮助如果觉得不错欢迎点赞、收藏、分享~作者铅笔小新z日期2025 年 12 月 16 日目标一篇讲透 C vector从使用到底层实现。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

房地产营销网站建设关键词怎么优化

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个高效的批量文件权限修改工具,主要功能:1. 可视化界面选择多个文件和目标用户/组;2. 智能识别文件类型和推荐权限设置;3. 生成…

张小明 2025/12/31 20:51:22 网站建设

做平面设计在那个网站上找图好cms进行网站开发

您是否曾因为记不住复杂的 Linux 命令参数而感到头疼?是否因为需要频繁切换多台服务器执行重复操作而感到疲惫?Wisdom SSH 正是为了解决这些痛点而诞生的,它不仅仅是一个传统的 SSH 客户端,更是一位集成 AI 运维助手的智能专家&am…

张小明 2025/12/31 20:50:50 网站建设

怎么建立手机网站建设用地规划许可证查询网站

在智慧建筑飞速发展的当下,楼宇自控、安防监控、消防报警、能耗监测等子系统如同建筑的“四肢”,支撑着日常运营的每一项功能。但在传统管理模式中,各子系统独立运行、数据互不互通,形成一道道“信息壁垒”,不仅导致设…

张小明 2025/12/31 20:49:46 网站建设

开发一个手机网站要多少钱响应式手机网站怎么做

文章介绍了一个基于钉钉平台的AI助手开源项目,整合了DeepSeek-V3大模型、Qdrant向量数据库、Redis记忆系统和LangGraph工具框架。通过智能对话、情感分析、意图识别、知识库检索和多工具调度等核心功能,帮助开发者掌握大模型深度集成、向量数据库构建、对…

张小明 2025/12/31 20:49:15 网站建设

做快消品看那些网站好高大上企业网站

第一章:从毫秒到微秒:边缘AI Agent推理速度的挑战与机遇 在边缘计算场景中,AI Agent 的实时性要求正从毫秒级向微秒级演进。这种性能跃迁不仅是技术指标的提升,更是对工业自动化、自动驾驶和实时交互系统能否落地的关键制约。 延…

张小明 2025/12/31 20:48:42 网站建设