vector 在 push_back 时的调用类对象的拷贝构造函数和析构函数有点特别,简单做下分析。

程序代码:

#include <iostream>
#include <vector>using namespace std;struct sss
{
public:explicit sss(int val) : value(val){cout << "---init sss " << this << ", value:" << value << endl;}sss(const sss& org){cout << "---copy " << &org << " to " << this << endl;value = org.value;}~sss(){cout << "---destory sss " << this << ", value:" << value << endl;}int value;
};int main(int argc, char ** argv)
{sss s_tmp(11);int i = 0;vector<sss> vvv;for (i = 0; i < 5; i++) {s_tmp.value++;vvv.push_back(s_tmp);cout << "size: " << vvv.size() << ", capacity: " << vvv.capacity() << endl;}return 0;
}

功能很简单,main 中定义一个 sss 类对象和对应的 vector,然后在循环中改类成员的值,并依次 push_back 到 vector 中,类的构造函数、析构函数、拷贝构造函数中都加了对应的打印输出。循环运行了5次,往 vector 中增加了5个类成员。

实际运行输出如下:


---init sss 0x22ff20, value:11
---copy 0x22ff20 to 0x5d2a58
size: 1, capacity: 1
---copy 0x5d2a58 to 0x5d2ad8
---copy 0x22ff20 to 0x5d2adc
---destory sss 0x5d2a58, value:12
size: 2, capacity: 2
---copy 0x5d2ad8 to 0x5d2ae8
---copy 0x5d2adc to 0x5d2aec
---copy 0x22ff20 to 0x5d2af0
---destory sss 0x5d2ad8, value:12
---destory sss 0x5d2adc, value:13
size: 3, capacity: 4
---copy 0x22ff20 to 0x5d2af4
size: 4, capacity: 4
---copy 0x5d2ae8 to 0x5d2b00
---copy 0x5d2aec to 0x5d2b04
---copy 0x5d2af0 to 0x5d2b08
---copy 0x5d2af4 to 0x5d2b0c
---copy 0x22ff20 to 0x5d2b10
---destory sss 0x5d2ae8, value:12
---destory sss 0x5d2aec, value:13
---destory sss 0x5d2af0, value:14
---destory sss 0x5d2af4, value:15
size: 5, capacity: 8
---destory sss 0x5d2b00, value:12
---destory sss 0x5d2b04, value:13
---destory sss 0x5d2b08, value:14
---destory sss 0x5d2b0c, value:15
---destory sss 0x5d2b10, value:16
---destory sss 0x22ff20, value:16


结果分析:

vector 每次调用 push_back 时都会拷贝一个新的参数指定的 sss 类对象,这会调用 sss 的拷贝构造函数,第一次的 copy 正常,而且 vector 的实际容量也由 0  变为 1。

第二次调用 push_back,通过输出会发现调用了两次拷贝构造函数,一次析构函数,原来 vector 此时判断容量不够,将容量扩大为原来的两倍,变为 2,并将原来的元素再次拷贝一份存放到新的内存空间,然后拷贝新加的类对象,最后再释放原来的元素。

第三次调用 push_back 时,vector 自动扩大为4,因此拷贝构造函数调用了3次,析构函数调用了2次,程序最终退出了时就析构了 5 次加本身的 sss 类对象一共 6 次。

参考:

由此看来,vector 的 push_back 在发现空间不足时自动将空间以 2 的指数增长:0 -> 1 -> 2 -> 4 -> 8 -> 16 -> 32 ...

查找资料后得知,如此设计的主要目的是为了尽可能的减小时间复杂度;如果每次都按实际的大小来增加 vector 的空间,会造成时间复杂度很高,降低 push_back 的速度。

另外关于 push_back 为什么会执行拷贝构造函数,push_back 的原型为:

void push_back(const _Ty& _Val)

参数是以引用方式传递,按说不会拷贝,但 push_back 实际实现中判断空间不足时是调用 insert 函数添加元素:

void push_back(const _Ty& _Val)
{// insert element at endif (size() < capacity())#if _HAS_ITERATOR_DEBUGGING{// room at end, construct it there_Orphan_range(_Mylast, _Mylast);_Mylast = _Ufill(_Mylast, 1, _Val);}#else /* _HAS_ITERATOR_DEBUGGING */_Mylast = _Ufill(_Mylast, 1, _Val);#endif /* _HAS_ITERATOR_DEBUGGING */elseinsert(end(), _Val);
}

引自:https://zohead.com/archives/vector-push-back-space-copy/

仅供个人学习

侵删

C++ vector向量pushback拷贝构造需要注意的几点相关推荐

  1. vector的push_back拷贝构造和空间占用分析

    本文同步自:http://zohead.com/archives/vector-push-back-space-copy/ 这两天在实际程序中使用 STL 的 vector push_back 类对象 ...

  2. c++ vector拷贝构造_vector------stl学习笔记一

    vector其中一个特点:内存空间只会增长,不会减小 援引C++ Primer:为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储. 设想一下,当vecto ...

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

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

  4. 基于java的数据结构学习——动态数组C++类模板(含拷贝构造,重载常见运算符)

    之前实现了java的动态数组,试着写了个C++版的,同样对时间复杂度振荡进行了处理.纯手打,代码如下 : // // Created by PC-Saw on 2018/12/19. //#ifnde ...

  5. C++之Big Three:拷贝构造、拷贝赋值、析构函数探究

    涉及到本文所讲知识点的博文: C++之析构函数探究 C++之常引用和浅拷贝探究 C++之一个函数链的简单例子(分文件实现) C++之Big Three:拷贝构造.拷贝赋值.析构函数探究 C++之操作符 ...

  6. E. 手机服务(构造+拷贝构造+堆)

    题目描述设计一个类来实现手机的功能.它包含私有属性:号码类型.号码. 号码状态.停机日期:包含方法:构造.拷贝构造.打印.停机. 1.号码类型表示用户类别,只用单个字母,A表示机构,B表示企业 .C表 ...

  7. 一步步带你观察vector.push_back()具体拷贝机制,超级详细哦

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

  8. H. 银行账户(拷贝构造)

    题目描述银行账户包括余额.利率.号码.类型等属性,其中号是固定8位整数,类型表示个人还是企业账户,如果是个人用P标识,企业用E标识.账户又分为活期账户和定期账户,活期利率为0.5%,定期利率为1.5% ...

  9. STL(模板库)(string)(vector向量)(2019.3.19晚课习题)

    STL,标准模板库,从根本上说是一些''容器''的集合,这些容器有list,vector,set,map等.STL也是一些算法和其他一些组建的集合,STL现在也是c++的一部分,因此不用安装额外的库文 ...

最新文章

  1. 重磅!GitHub 日收 7000 星, Windows 计算器项目开源即爆红!
  2. 王兴:一鸣开始动手了
  3. java 调用windows bat脚本
  4. java中 快捷键输入System.out.println();
  5. python 数组赋值_LeetCode基础算法题第182篇:一维数组的运行总和
  6. struts2 s:optiontransferselect 标签的使用
  7. mysql 开启守护进程_[求助]Linux上MySQL Server 5.6 安装后无法启动守护进程
  8. 【Lucene】Lucene的使用和优化
  9. python学习笔记-day2-dict,tuple, string常用函数
  10. Vs快捷键设置(可搭配Vim使用)
  11. pat03-树3. Tree Traversals Again (25)
  12. ORACLE 12c RAC的常用管理命令
  13. 【 Codeforces Round #552 (Div. 3) G】Minimum Possible LCM【埃氏筛】
  14. 一种破解静态链接库(.lib)的简单方法
  15. xlsxwriter
  16. DT741-csf联通创维光猫桥接模式+华为WS5200路由器拨号设置
  17. Abel逆变换的MATLAB实现(未完成版)
  18. linux 怎么临时修改ip,linux中临时、永久修改ip(示例代码)
  19. 零代码变更,巧用 Reloader 快速实现 Kubernetes 的 Configmap 和 Secret 热更新
  20. node.js学习的资源整理

热门文章

  1. 瞬间高逼格!这 6 种 Python 进度条真的绝了!
  2. 中国国画能用计算机吗,电脑中国画图片
  3. 嵌入式C语言自我修养 04:Linux 内核第一宏:container_of
  4. 生活方式2006创意博起
  5. Mock测试工具篇---Fiddler的使用
  6. Apache POI 读取 Word 表格数据(doc 和 docx 后缀)
  7. 简单二叉树Java代码实现
  8. 自动关机HTA桌面小程序实现源码
  9. linux 卸载 rpm e,Linux rpm -e --nodeps rpm卸载
  10. 关于RSA加密技术的使用,js前端加密,Golang 后端解密 详细