一步步带你观察vector.push_back()具体拷贝机制,超级详细哦
目录
- 观察vector.push_back()具体拷贝机制
- 实验需要条件
- 实验代码:
- 实验结果:
- 分析实验结果
- 步骤1
- 步骤2
- 步骤3
- 步骤4
- 步骤5
- 步骤6
- 步骤7
- 步骤8&9
- 步骤10
- 实验结论:
观察vector.push_back()具体拷贝机制
实验需要条件
- vector容器
- 创建一个能通过拷贝控制函数打印相关信息的类,这里我自己写了一个简易的String类来打印信息
实验代码:
vector<String> vec;String s = "1";cout << "--------第一个放入容器-------" << endl;vec.push_back(s);cout << "--------第二个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第三个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第四个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第五个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第六个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第七个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第八个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第九个元素放入容器-------" << endl;vec.push_back(s);cout << "--------第十个元素放入容器-------" << endl;vec.push_back(s);cout << "--------放入完毕-------" << endl;
实验结果:
分析实验结果
看到实验结果一开始是头皮发麻的,其实通过查找规律,可以验证侯杰老师在深入理解STL源码
中所说的vector容器大小1.5倍增长
步骤1
vec.push_back(s);
实验结果:
实验结果很显然符合我们的预期,调用push_back
函数时,拷贝一次s
,此时vector容器
大小为1
步骤2
vec.push_back(s);
vec.push_back(s);
实验结果:
这时候结果开始令人费解了,我们预期应该调用两次拷贝构造函数,为什么这里出现了一次移动构造函数
与一次析构函数
,没关系,这时候我们先记住此时容器大小为2
就行,继续下一步
步骤3
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
实验结果:
第三次push_back
不出我们所料,令人费解的出现了两次移动构造函数
与两次析构函数
此时容器大小为3
步骤4
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
实验结果:
此时容器大小为4
步骤5
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
实验结果:
此时容器大小为5
完蛋了,都已经push_back五个元素了,还是令人费解,难道要寄了吗?!最后一次push_back,还不出现转机直接不干了!
步骤6
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
实验结果:
我的天啊,当我们push_back
第六个元素的时候出现不一样的结果了,开心!这时候居然只出现了一次拷贝构造函数
,此时容器大小是6
步骤7
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
实验结果:
该死,第七次又出现了奇奇怪怪的移动构造函数与析构函数
此时容器大小为7
步骤8&9
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
第八和第九次都只构造了一次,此时容器大小为9
步骤10
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
vec.push_back(s);
结果我就不放了,第十次依然是出现了奇怪的移动构造函数与析构函数
此时容器大小为10
这个时候我回想起之前侯杰老师所讲的vector容器1.5倍增长的结论,心中的疑惑解除了
在这里我们要搞清vec.size()与vec.capacity()的区别
vec.size() | vec.capacity() |
---|---|
容器目前容纳的元素个数 | 容器最大容纳元素个数 |
而且满足vec.size()<=vec.capacity()
一旦vec.size()>vec.capacity()
vec会重新分配一块更大的空间,并且容量为之前容量的1.5倍
,这就是所谓的1.5倍增长
。然而,开辟了新的空间,我们需要把旧空间的元素
拷贝到新空间
去,但由于旧元素
被拷贝
后就不会再用
了,此时我们可以使用移动构造函数
让新空间窃取
旧空间的元素权限,以减少拷贝所带来的时间开销,同时,旧空间需要被摧毁。
上面的这段操作不就和步骤2、3、4、5、7、10
所伴随的奇奇怪怪的移动构造函数
与析构函数
很相似吗,为了描述方便,我将这段操作简述为出现增长
所谓的1.5倍增长指的是vector的最大容纳元素个数!
通过结论,我们可以模拟一下vector增长的过程
这里初始时vector容器大小为1
最大容纳元素个数增长过程:
1 -> 2 -> 3 -> 4 -> 6 -> 9
我们可以模拟一下push_back时候vec的最大容量capacity
,就会发现秘密了!
步骤2:出现增长
此时capacity
为1
,size
为1
,push_back
后size=2>capacity=1
,需要重新分配空间,并且出现将旧空间
的1个
元素移动到新空间,析构旧空间的1个
元素,符合实验结果调用一次
移动构造函数与一次
析构函数
步骤3:出现增长
此时capacity
为2
,size
为2
,push_back
后size=3>capacity=2
,需要重新分配空间,并且出现将旧空间
的2个
元素移动到新空间,析构旧空间的2个
元素,符合实验结果调用两次
移动构造函数与两次
析构函数
步骤4:出现增长
此时capacity
为3
,size
为3
,push_back
后size=4>capacity=3
,需要重新分配空间,并且出现将旧空间
的3个
元素移动到新空间,析构旧空间的3个
元素,符合实验结果调用三次
移动构造函数与三次
析构函数
步骤5:出现增长
此时capacity
为4
,size
为4
,push_back
后size=5>capacity=4
,需要重新分配空间,并且出现将旧空间
的4个
元素移动到新空间,析构旧空间的4个
元素,符合实验结果调用四次
移动构造函数与四次
析构函数
步骤6:
此时capacity
为6
,size
为5
,push_back
后size=6=capacity=6
,不需要重新分配空间,因为最大容纳空间还足以满足分配元素的需求
步骤7:出现增长
此时capacity
为6
,size
为6
,push_back
后size=7>=capacity=6
,需要重新分配空间,并且出现将旧空间
的6个
元素移动到新空间,析构旧空间的6个
元素,符合实验结果调用六次
移动构造函数与六次
析构函数
步骤8:
此时capacity
为9
,size
为7
,push_back
后size=8<capacity=9
,不需要重新分配空间,因为最大容纳空间还足以满足分配元素的需求
步骤9:
此时capacity
为9
,size
为8
,push_back
后size=9=capacity=9
,不需要重新分配空间,因为最大容纳空间还足以满足分配元素的需求
步骤10:出现增长
此时capacity
为9
,size
为9
,push_back
后size=10>capacity=9
,需要重新分配空间,并且出现将旧空间
的9个
元素移动到新空间,析构旧空间的9个
元素,符合实验结果调用九次
移动构造函数与九次
析构函数
步骤11:通过实验结果我们可以预测步骤11不会出现增长
此时capacity
为13
,size
为10
,push_back
后size=11<capacity=13
实验结论:
原来啊,步骤2、步骤3、步骤4、步骤5、步骤7、步骤10
出现奇奇怪怪的移动与析构函数是因为push_back元素的时候发生了size>capacity
,此时需要将最大容纳空间向1.5倍
扩充,以满足增加元素的需求!至于步骤1、步骤6、步骤8、步骤9
因为满足size<=capacity
,所以可以直接在旧空间上增加元素,而不需要重新分配一段1.5倍率
的内存空间
一步步带你观察vector.push_back()具体拷贝机制,超级详细哦相关推荐
- 从零开始一起学习SLAM | 理解图优化,一步步带你看懂g2o代码
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 小白:师兄师兄,最近我在看SLAM的优化算法,有种方法叫" ...
- 一步步带你做vue后台管理框架(三)——登录功能
系列教程<一步步带你做vue后台管理框架>第三课 github地址:vue-framework-wz 线上体验地址:立即体验 <一步步带你做vue后台管理框架>第一课:介绍框架 ...
- Java:一步步带你深入了解神秘的Java反射机制
Java:一步步带你深入了解神秘的Java反射机制· 前言 在 Java中,反射机制(Reflection)非常重要,但对于很多开发者来说,这并不容易理解,甚至觉得有点神秘 今天,我将献上一份 Jav ...
- C++11介绍之vector::push_back和vector::emplace_back区别
vector::push_back和vector::emplace_back区别 emplace_back() 和 push_back() 功能上类似,但底层实现机制是不同的.push_back() ...
- 一步步带你做vue后台管理框架(二)——上手使用 系列教程《一步步带你做vue后台管理框架》第二课
github地址:vue-framework-wz 线上体验地址:立即体验 <一步步带你做vue后台管理框架>第一课:介绍框架 <一步步带你做vue后台管理框架>第二课:上手使 ...
- vue族谱架构_一步步带你做vue后台管理框架(一)——介绍框架
系列教程<一步步带你做vue后台管理框架>第一课 线上体验地址:立即体验 Features 特性
- 一步步带你实现一个简单的express服务器,能让vue通过axios请求将图片上传到阿里云OSS
文章目录 前言 一.申请阿里云OSS 二.Vue前端读取图片 三.将图片base64转成二进制文件 四.搭建express服务器 五.通过axios给服务器发送请求 六.发送图片并上传阿里云 我们首先 ...
- STL中Vector的内存分配机制
一些好的公司校园招聘过程中(包括笔试.面试环节),经常会涉及到STL中vector的使用(主要是笔试)及其性能(面试)的分析.今天看了下相关文章,也写了几个小的测试程序跑了跑.算是总结下,希望对需要的 ...
- 关于c++中vector的push_back、拷贝构造copy constructor和移动构造move constructor
问题来自C++ Primer的第十三章练习题的13.48.是这样说的: 定义一个vector<String>并在其上多次调用push_back运行你的程序,并观察String被拷贝了多少次 ...
最新文章
- 模拟usb设备_高速USB数据采集卡
- Android Studio签名打包的两种方式
- Android中的帧布局
- linux文件一列加1,Linux命令(1)-创建文件
- python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存
- oracle 监控 视图,【转】oracle几个常用的监控视图
- 微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面
- 前端学习(1165):扩展运算符01
- 安卓恶意软件Skygofree爆发,连你的照片都能监控到
- Kotlin 的工作原理
- python 反弹shell,加了UDP
- 互联网协议入门(三)
- 完美世界国际版不用外挂多开的方法
- day8--socket回顾
- 网心科技 | 三分钟带你了解中国CDN发展史
- 移动端事件--touch事件的分类、touch事件的event对象、 其他触摸事件
- c语言程序设计答案苏小红,C语言程序设计苏小红版答案[推荐阅读]
- dd命令详解(原创)
- Android 一种关于解决 No view found for id xxxx for fragment xxxx 问题的方案
- 告别尴尬,自在出行,就选电动车排名前十名的绿源
热门文章
- java SpringBoot 对接支付宝 APP支付 证书模式及非证书模式
- 【Java设计模式】——单例模式
- 网站点击弹窗微信二维码功能纯CSS
- USB over Network通过本地网络或 Internet 共享的远程 USB 设备
- 2020-05-21
- [SCOI2009]windy数
- ORA-01653: 表 xxx 无法通过 (在表空间 xxx 中) 扩展
- AFX_MODULE_STATE作用
- 新元宇宙每周连载《地球人奇游天球记》第十三回火星烧烤
- 解决kubernetes启动容器时,容器一直是ContainerCreating不能running