目录

  • 观察vector.push_back()具体拷贝机制
    • 实验需要条件
    • 实验代码:
    • 实验结果:
    • 分析实验结果
      • 步骤1
      • 步骤2
      • 步骤3
      • 步骤4
      • 步骤5
      • 步骤6
      • 步骤7
      • 步骤8&9
      • 步骤10
    • 实验结论:

观察vector.push_back()具体拷贝机制

实验需要条件

  1. vector容器
  2. 创建一个能通过拷贝控制函数打印相关信息的类,这里我自己写了一个简易的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:出现增长
此时capacity1size1push_backsize=2>capacity=1,需要重新分配空间,并且出现将旧空间1个元素移动到新空间,析构旧空间的1个元素,符合实验结果调用一次移动构造函数与一次析构函数

步骤3:出现增长
此时capacity2size2push_backsize=3>capacity=2,需要重新分配空间,并且出现将旧空间2个元素移动到新空间,析构旧空间的2个元素,符合实验结果调用两次移动构造函数与两次析构函数

步骤4:出现增长
此时capacity3size3push_backsize=4>capacity=3,需要重新分配空间,并且出现将旧空间3个元素移动到新空间,析构旧空间的3个元素,符合实验结果调用三次移动构造函数与三次析构函数

步骤5:出现增长
此时capacity4size4push_backsize=5>capacity=4,需要重新分配空间,并且出现将旧空间4个元素移动到新空间,析构旧空间的4个元素,符合实验结果调用四次移动构造函数与四次析构函数

步骤6:
此时capacity6size5push_backsize=6=capacity=6,不需要重新分配空间,因为最大容纳空间还足以满足分配元素的需求

步骤7:出现增长
此时capacity6size6push_backsize=7>=capacity=6,需要重新分配空间,并且出现将旧空间6个元素移动到新空间,析构旧空间的6个元素,符合实验结果调用六次移动构造函数与六次析构函数

步骤8:
此时capacity9size7push_backsize=8<capacity=9,不需要重新分配空间,因为最大容纳空间还足以满足分配元素的需求

步骤9:
此时capacity9size8push_backsize=9=capacity=9,不需要重新分配空间,因为最大容纳空间还足以满足分配元素的需求

步骤10:出现增长
此时capacity9size9push_backsize=10>capacity=9,需要重新分配空间,并且出现将旧空间9个元素移动到新空间,析构旧空间的9个元素,符合实验结果调用九次移动构造函数与九次析构函数

步骤11:通过实验结果我们可以预测步骤11不会出现增长
此时capacity13size10push_backsize=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()具体拷贝机制,超级详细哦相关推荐

  1. 从零开始一起学习SLAM | 理解图优化,一步步带你看懂g2o代码

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 小白:师兄师兄,最近我在看SLAM的优化算法,有种方法叫" ...

  2. 一步步带你做vue后台管理框架(三)——登录功能

    系列教程<一步步带你做vue后台管理框架>第三课 github地址:vue-framework-wz 线上体验地址:立即体验 <一步步带你做vue后台管理框架>第一课:介绍框架 ...

  3. Java:一步步带你深入了解神秘的Java反射机制

    Java:一步步带你深入了解神秘的Java反射机制· 前言 在 Java中,反射机制(Reflection)非常重要,但对于很多开发者来说,这并不容易理解,甚至觉得有点神秘 今天,我将献上一份 Jav ...

  4. C++11介绍之vector::push_back和vector::emplace_back区别

    vector::push_back和vector::emplace_back区别 emplace_back() 和 push_back() 功能上类似,但底层实现机制是不同的.push_back() ...

  5. 一步步带你做vue后台管理框架(二)——上手使用 系列教程《一步步带你做vue后台管理框架》第二课

    github地址:vue-framework-wz 线上体验地址:立即体验 <一步步带你做vue后台管理框架>第一课:介绍框架 <一步步带你做vue后台管理框架>第二课:上手使 ...

  6. vue族谱架构_一步步带你做vue后台管理框架(一)——介绍框架

    系列教程<一步步带你做vue后台管理框架>第一课 线上体验地址:立即体验 Features 特性

  7. 一步步带你实现一个简单的express服务器,能让vue通过axios请求将图片上传到阿里云OSS

    文章目录 前言 一.申请阿里云OSS 二.Vue前端读取图片 三.将图片base64转成二进制文件 四.搭建express服务器 五.通过axios给服务器发送请求 六.发送图片并上传阿里云 我们首先 ...

  8. STL中Vector的内存分配机制

    一些好的公司校园招聘过程中(包括笔试.面试环节),经常会涉及到STL中vector的使用(主要是笔试)及其性能(面试)的分析.今天看了下相关文章,也写了几个小的测试程序跑了跑.算是总结下,希望对需要的 ...

  9. 关于c++中vector的push_back、拷贝构造copy constructor和移动构造move constructor

    问题来自C++ Primer的第十三章练习题的13.48.是这样说的: 定义一个vector<String>并在其上多次调用push_back运行你的程序,并观察String被拷贝了多少次 ...

最新文章

  1. 模拟usb设备_高速USB数据采集卡
  2. Android Studio签名打包的两种方式
  3. Android中的帧布局
  4. linux文件一列加1,Linux命令(1)-创建文件
  5. python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存
  6. oracle 监控 视图,【转】oracle几个常用的监控视图
  7. 微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面
  8. 前端学习(1165):扩展运算符01
  9. 安卓恶意软件Skygofree爆发,连你的照片都能监控到
  10. Kotlin 的工作原理
  11. python 反弹shell,加了UDP
  12. 互联网协议入门(三)
  13. 完美世界国际版不用外挂多开的方法
  14. day8--socket回顾
  15. 网心科技 | 三分钟带你了解中国CDN发展史
  16. 移动端事件--touch事件的分类、touch事件的event对象、 其他触摸事件
  17. c语言程序设计答案苏小红,C语言程序设计苏小红版答案[推荐阅读]
  18. dd命令详解(原创)
  19. Android 一种关于解决 No view found for id xxxx for fragment xxxx 问题的方案
  20. 告别尴尬,自在出行,就选电动车排名前十名的绿源

热门文章

  1. java SpringBoot 对接支付宝 APP支付 证书模式及非证书模式
  2. 【Java设计模式】——单例模式
  3. 网站点击弹窗微信二维码功能纯CSS
  4. USB over Network通过本地网络或 Internet 共享的远程 USB 设备
  5. 2020-05-21
  6. [SCOI2009]windy数
  7. ORA-01653: 表 xxx 无法通过 (在表空间 xxx 中) 扩展
  8. AFX_MODULE_STATE作用
  9. 新元宇宙每周连载《地球人奇游天球记》第十三回火星烧烤
  10. 解决kubernetes启动容器时,容器一直是ContainerCreating不能running