记录C++中,vector的迭代器在push_back以后扩容导致迭代器失效的问题

前言

        vector是我们用到最多的数据结构,其底层数据结构是单端动态数组,由于数组的特点,vector也具有以下特性: ①O(1)时间的快速访问; ②顺序存储,所以插入到非尾结点位置所需时间复杂度为O(n),删除也一样; ③扩容规则: 当我们新建一个vector的时候,会首先分配给他一片连续的内存空间,如std::vector vec,当通过push_back向其中增加元素时,如果初始分配空间已满,就会引起vector扩容,其扩容规则在gcc下以2倍方式完成:

  •         首先重新申请一个2倍大的内存空间;
  •         然后将原空间的内容拷贝过来;
  •         最后将原空间内容进行释放,将内存交还给操作系统;


注意事项:根据vector的插入和删除特性,以及扩容规则,我们在使用vector的时候要注意,在插入位置和删除位置之后的所有迭代器和指针引用都会失效,同理,扩容之后的所有迭代器指针和引用也都会失效。

原文链接:https://blog.csdn.net/qq_45311905/article/details/117020436

问题1:使用{}赋值,会丧失扩容功能

        vector的最原始大小是0,如果使用{}方法去赋值,那么会丧失扩容功能

#include <iostream>
#include <vector>int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};// 获取第二个元素的迭代器auto it = numbers.begin() + 1;// 在第二个位置插入一个新元素,导致vector扩容numbers.insert(numbers.begin() + 1, 10);// 尝试访问迭代器指向的元素,会导致未定义行为    会打印随机值std::cout << "Value at iterator: " << *it << std::endl;// 实际值:std::cout << "Value at iterator: " << numbers[1] << std::endl;return 0;
}

会发现打印随机值

如果不使用{}就没问题:

#include <iostream>
#include <vector>int main() {std::vector<int> numbers;numbers.push_back(1);numbers.push_back(2);numbers.push_back(3);numbers.push_back(4);numbers.push_back(5);// 获取第二个元素的迭代器auto it = numbers.begin() + 1;// 在第二个位置插入一个新元素,导致vector扩容numbers.insert(numbers.begin() + 1, 10);// 尝试访问迭代器指向的元素,会导致未定义行为    会打印随机值std::cout << "Value at iterator: " << *it << std::endl;// 实际值:std::cout << "Value at iterator: " << numbers[1] << std::endl;return 0;
}

问题2:在push_back()以后,继续使用迭代器会触发扩容导致迭代器失效

#include <iostream>
#include <vector>int main() {std::vector<int> numbers;size_t max_capacity = 0;max_capacity = numbers.capacity();std::cout<<"max:"<<max_capacity<<std::endl;		// 0// 第一次添加数据,会导致第一次扩容numbers.push_back(100);auto it = numbers.begin() + 0;std::cout<<"*it:"<<*it<<std::endl;std::cout<<"number[0]:"<<numbers[0]<<std::endl;std::cout<<std::endl;// 第二次添加数据,会导致第二次扩容,迭代器失效,下标法不会失效numbers.push_back(2);max_capacity = numbers.capacity();std::cout<<"max:"<<max_capacity<<std::endl;std::cout<<"*it:"<<*it<<std::endl;std::cout<<"number[0]:"<<numbers[0]<<std::endl;it = numbers.begin() + 0;std::cout<<"new *it:"<<*it<<std::endl;std::cout<<std::endl;// 第三次添加数据,会导致第三次扩容,但是发现迭代器并没有失效,下标法不会失效numbers.push_back(2);numbers.push_back(2);numbers.push_back(2);numbers.push_back(2);max_capacity = numbers.capacity();std::cout<<"max:"<<max_capacity<<std::endl;std::cout<<"*it:"<<*it<<std::endl;std::cout<<"number[0]:"<<numbers[0]<<std::endl;it = numbers.begin() + 0;std::cout<<"new *it:"<<*it<<std::endl;std::cout<<std::endl;//  因为一种在增加,所以发现程序所占内存越来越大	
//	for (int i = 1; ; ++i) {
//		numbers.push_back(i);
//		if (numbers.size() > numbers.capacity()) {
//			max_capacity = numbers.size() - 1;
//			break;
//		}
//	}return 0;
}

        原因是,在最开始的时候,vector的容量是0,随着push-back,会不断 x2 的去增加容量,但是增加容量的时候,最开始获取的迭代器指针去获取数据的方式就失效了,不过好在使用下标并不会失效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/577669.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARMv8-A架构下的外部debug模型(external debug)简介

Armv8-A external debug Armv8-A debug模型一&#xff0c;外部调试 External debug 简介二&#xff0c;Debug state2.1 Debug state的进入与退出 三&#xff0c;DAP&#xff0c;Debug Access Port3.1 EDSCR, External Debug Status and Control Register调试状态标识&#xff0…

小型分布式文件存储系统GoFastDfs应用简介

前言 最近稍微留意了一下各个文件存储系统的协议&#xff0c;发现minio是LGPLV3, 而fastdfs 是GPL3,这些协议其实对于商业应用是一个大坑。故而寻找一些代替品。 go-fastdfs就是其中之一&#xff0c;官网在&#xff1a; go-fastdfs 具体应用 其实可以直接查看官网教程的。 下…

代码随想录学习Day 21

回溯算法理论基础 回溯法又叫回溯搜索法。回溯是递归的副产品&#xff0c;有递归就会有回溯&#xff0c;回溯操作一般出现在递归函数的下面。回溯函数 递归函数。回溯法的本质是穷举。 回溯法解决的问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集…

47 vue 常见的几种模型视图不同步的问题

前言 这里主要是来看一下 关于 vue 中的一些场景下面 可能会出现 模型和视图 不同步更新的情况 然后 这种情况主要是 vue 中的对象 属性没有响应式的 setter, getter 然后 我们这里就来看一下 大多数的情况下的一个场景, 和一些处理方式 当然 处理方式主要是基于 Vue.set, …

4t第14届省赛模拟1

俺服了&#xff0c;原来是\r\n写里边了....... 不过他都测55cm的超声波 是把距离测量值赋给距离参数&#xff0c;俺看反了&#xff0c;然后还加了一个标志位让超声波不进行读取然后显示距离参数值...... 好像用int和char没啥关系&#xff0c;就是后面强制类型转换串口显示都…

机器学习算法的另一个分支-贝叶斯算法原理(贝叶斯要解决什么问题)

目录 一、贝叶斯简介 二、贝叶斯要解决的问题 三、例子&#xff08;公式推导&#xff09; 四、实例 1. 拼写纠正实例 2. 垃圾邮件过滤实例 一、贝叶斯简介 1. 贝叶斯&#xff1a;英国数学家。1702年出生于伦敦&#xff0c;做过神甫。贝叶斯在数学方面主要研究概率论.对于…

『大模型笔记』提示工程、微调和RAG之间对比

提示工程、微调和RAG之间对比 文章目录 一. 提示工程、微调和RAG之间对比二. 参考文章文章:Prompt Engineering vs Finetuning vs RAG一. 提示工程、微调和RAG之间对比 Prompt EngineeringFinetuning

基于springboot的月子会所系统

摘 要 随着时代的进步&#xff0c;人们对生活的要求越来越高。月子基本是每一个生育期的母亲都要精力的一个特殊阶段&#xff0c;在中国人的传统观念中月子是一个非常重要的时期&#xff0c;只有在月子期间得到更好的照顾才能尽快的康复。传统的家庭一般都缺少月子期间对母婴照…

【干货分享】OpenHarmony轻量系统适配方案

1. 简介 本文在不改变原有系统基础框架的基础上&#xff0c; 介绍了一种OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;轻量系统适配方案。 本方案使用的是 OpenHarmony v3.2 Release版本源码。 2. 方案设计 本文使用的硬件模块的主要特性及功能如…

4/1 背刺!春招B站一面,这些问题你都会吗?

❝ 下面我将分享一位同学在Bilibili一面的面试经历&#xff0c;对于这次面试&#xff0c;他的评价是&#xff0c;「很有难度」&#xff0c;你试试呢&#xff1f; ❞ 【提醒】通过这次面试经验&#xff0c;你将可以复习到以下知识点&#xff0c;注意汇总&#xff0c;不超过10个 …

git的使用日常习惯规范与一些特殊操作

git的使用日常习惯规范与一些特殊操作 操作习惯规范创建本地新分支&#xff0c;推送新分支到云端仓库1.创建一个本地的login分支2.创建新分支后切换到新分支3.推送新分支到云端 git的特殊操作撤回commit&#xff08;取消提交到本地版本库的动作&#xff0c;本地工作区写的代码不…

c语言游戏实战(7):扫雷

前言&#xff1a; 扫雷是一款经典的单人益智游戏&#xff0c;它的目标是在一个方格矩阵中找出所有的地雷&#xff0c;而不触碰到任何一颗地雷。在计算机编程领域&#xff0c;扫雷也是一个非常受欢迎的项目&#xff0c;因为它涉及到许多重要的编程概念&#xff0c;如数组、循环…