C++primer第九章 顺序容器 9.4 vector对象是如何增长的

  • 为了支持快速随机访问,vector将元素连续存储,每个元素紧挨着前一个元素存储。通常情况下,我们不必关心一个标准库类型是如何实现的,而只需关心它如何使用。然而,对于vector和string,其部分实现渗透到了接口中。
  • 假定容器中元素是连续存储的,且容器的大小是可变的,考虑向vector或string中添加元素会发生什么:如果没有空间容纳新元素,容器不可能简单地将它添加到内存中其他位置--因为元素必须连续存储。容器必须分配新的内存空间来保存已有元素和新元素,已有元素从旧位置移动到新空间中,然后添加新元素,释放旧存储空间。如果我们每添加一个新元素,vector就执行一次这样的内存分配和释放操作,性能会慢到不可接受。为了避免这种代价,标准库实现者采用了可以减少容器空间重新分配次数的策略。当不得不获取新的内存空间时,vector和string的实现通常会分配比新的空间需求更大的内存空间。容器预留这些空间作为备用,可用来保存更多的新元素(提前分配更大的空间)。这样,就不需要每次添加新元素都重新分配容器的内存空间了。这种分配策略比每次添加新元素时都重新分配容器内存空间的策略要高效得多。其实际性能也表现得足够好--虽然vector在每次重新分配内存空间时都要移动所有元素,但使用此策略后,其扩张操作通常比list和deque还要快。

管理容量的成员函数

  • 如表9.10所示,vector和string类型提供了一些成员函数,允许我们与它的实现中内存分配部分互动。capacity操作告诉我们容器在不扩张内存空间的情况下可以容纳多少个元素。reserve操作允许我们通知容器它应该准备保存多少个元素。

  • 有当需要的内存空间超过当前容量时,reserve调用才会改变vector的容量。如果需求大小大于当前容量,reserve至少分配与需求一样大的内存空间(可能更大)。如果需求大小小于或等于当前容量,reserve什么也不做。特别是,当需求大小小于当前容量时,容器不会退回内存空间。因此,在调用reserve之后,capacity将会大于或等于传递给reserve的参数。这样,调用reserve永远也不会减少容器占用的内存空间。类似的,resize成员函数(参见9.3.5节,第314页)只改变容器中元素的数目,而不是容器的容量。我们同样不能使用resize来减少容器预留的内存空间。
  • 在新标准库中,我们可以调用shrink_to_fit来要求deque、vector或string退回不需要的内存空间。此函数指出我们不再需要任何多余的内存空间。但是,具体的实现可以选择忽略此请求。也就是说,调用shrink_to_fit也并不保证一定退回内存空间。

capacity和size

  • 理解capacity和size的区别非常重要。容器的size是指它已经保存的元素的数目;而capacity则是在不分配新的内存空间的前提下它最多可以保存多少元素。下面的代码展示了size和capacity之间的相互作用
vector<int> ivec;
//size 应该为0 capacity应该依赖于具体实现
cout << "ivec:size: " <<ivec.size()<< "capacity: "  <<ivec.capacity() << endl;
//向ivec 添加24个元素
for(vector<int>::size_type ix = 0; ix != 24; ix++){ivec.push_back(ix);
}
//size 应该为24 capacity应该大于等于24 具体依赖于标准库的实现
cout << "ivec:size: " <<ivec.size()<< "capacity: "  <<ivec.capacity() << endl;
  • 当在我们的系统上运行时,这段程序得到如下输出:
  • ivec:size:0 capacity:0
  • ivec:size:24 capacity:32
  • 我们知道一个空vector的size为0,显然在我们的标准库实现中一个空vector的capacity也为0。当向vector中添加元素时,我们知道size与添加的元素数目相等。而capacity至少与size一样大,具体会分配多少额外空间则视标准库具体实现而定。在我们的标准库实现中,每次添加1个元素,共添加24个元素,会使capacity变为32。可以想象ivec的当前状态如下图所示:

  • 现在可以预先分配一些额外的空间
  • ivec.reserve(50);//将capacity的容量设置至少为50 可能会更大
  • size的大小应该为24,capacity的大小应该大于等于50 具体依赖于标准库的实现
  • 添加元素用光预留空间 while(ivec.size() != ivec.capacity()){ ivec.push_back(0);}
  • 只要使用的空间没有超过vector的容量,就不需要为此重新分配空间
  • 使用shrink_to_fit将vector超出当前大小的多余内存空间退回给系统
  • ivec.shrink_to_fit(); 要求归还内存。这仅仅是一个请求,是否归还并无保证
  • 每个vector实现都可以选择自己的内存分配策略。但是必须遵守的一条原则 ,是 :只有当迫不得已时才可以分配新的内存空间
  • 只有在执行insert操作时size与capacity相等,或者调用resize或reserve时给定的大小超过当前capacity,vector才可能重新分配内存空间。会分配多少超过给定容量的额外空间,取决于具体实现。
  • 虽然不同的实现可以采用不同的分配策略,但所有实现都应遵循一个原则:确保用push_back向vector添加元素的操作有高效率。从技术角度说,就是通过在一个初始为空的vector上调用n次push_back来创建一个n个元素的vector,所花费的时间不能超过n的常数倍

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

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

相关文章

codeforces 281A-C语言解题报告

281A题目网址 题目解析 1.字符串首字母大写 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int main() {char s[1000]{\0};scanf("%s",s);if(s[0]>A&&s[0]<Z){printf("%s",s…

SpringBoot 配置文件bootstrap和application的区别

目录一、SpringBoot配置文件二、bootstrap和application区别三、bootstrap和application的应用场景一、SpringBoot配置文件 bootstrap&#xff08;.yml 或者 .properties&#xff09; application&#xff08;.yml 或者 .properties&#xff09; 二、bootstrap和application区…

C++primer第九章 顺序容器 9.5 额外的string操作

除了顺序容器共同的操作之外&#xff0c;string类型还提供了一些额外的操作。这些操作中 的大部分要么是提供string类和C 风格字符数组之间的相互转换,要么是增加了允许我们用下标代替迭代器的版本。标准库string类型定义了大量函数。幸运的是&#xff0c;这些函数使用了重复的…

Zookeeper Mac下安装操作

目录一、下载Zookeeper二、修改配置1、设置启动配置文件2、修改配置三、启动Zookeeper服务命令1、bin目录下执行&#xff08;1&#xff09;启动Zookeeper命令&#xff08;2&#xff09;查看Zookeeper状态命令&#xff08;3&#xff09;停止Zookeeper命令2、配置环境变量执行&am…

codeforces 266A-C语言解题报告

266A题目网址 题目解析 1.输入n(1–50)个石头个数,输入RGB的石头颜色,求问拿走最小的石头个数,让它们相邻的石头颜色不同 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n,i,count0;char s[50]{\0};scanf("%d&quo…

2014年考研英语二作文PartB图表题

作文详细解析 题目 Write an essay based on the following chart, in which you should interpret the chart, and give your comments You should write about 150 words on the ANSWER SHEET.(15 points) 注意点 1.图表题在第一段描述图表信息时,一定要写清楚y轴变化…

Zookeeper 终端命令

目录一、服务端命令1、启动Zookeeper服务命令2、查看Zookeeper状态命令3、停止Zookeeper服务命令4、启动Zookeeper客户端命令二、客户端命令1、查看帮助2、查看当前znode所包含的内容3、创建znode4、创建短暂znode5、创建带序号znode6、创建短暂带序号znode7、获取znode数据8、…

C++primer第九章 顺序容器 9.6 容器适配器

9.6容器适配器 除了顺序容器外&#xff0c;标准库还定义了三个顺序容器适配器&#xff1a;stack、queue和priority_queue适配器(adaptor)是标准库中的一个通用概念。容器、迭代器和函数<369I都有适配器。本质上&#xff0c;一个适配器是一种机制&#xff0c;能使某种事物的…

codeforces 236A-C语言解题报告

236题目网址 题目解析 1.输入字符串,判断其中不同的字符个数,奇偶输出不同的语句 2.使用冒泡排序去排序,当遇到s[k]!s[k1]时进行计数 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {char s [100]{\0};int i,j,k,count0;cha…

SpringBoot Controller接收参数的常用方式

文章目录一、请求路径参数1、PathVariable二、Body参数1、RequestParam2、RequestBody三、请求头参数和Cookie参数1、RequestHeader2、CookieValue一、请求路径参数 1、PathVariable 注解为&#xff1a; org.springframework.web.bind.annotation.PathVariable获取路径参数&…

C++primer第十章 泛型算法 10.1 概述 10.2 初识泛型算法

大多数算法都定义在头文件algorithm中。标准库还在头文件numeric中定义了 一组数值泛型算法一般情况下&#xff0c;这些算法并不直接操作容器&#xff0c;而是遍历由两个迭代器指定的一个元素范围(参见9.2.1节&#xff0c;第296页)来进行操作。通常情况下&#xff0c;算法遍历范…

MySQL Mac安装教程

文章目录一、下载安装包二、安装三、启动MySQL四、环境变量设置一、下载安装包 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 二、安装 双击安装包&#xff0c;然后一直点继续即可。 三、启动MySQL 打开 系统偏好设置&#xff0c;会发现多了一个…

codeforces 96A-C语言解题报告

96A题目网址 题目解析 1.输入0和1表示不同队的队员字符串,如果7个及以上的一个0或1在一起,则输出YES否则输出NO 举例: 输入: 1000000001 输出: YES 2.循环时,当遇到count7时输出YES并跳出循环,遇到s[i]!s[i1]时,将count重置为1,最后count<7再输出NO 代码 #include<s…

C++生成指定范围内的随机数

代码 rand&#xff08;&#xff09;% 3 &#xff1b; 3就是范围&#xff0c;代表生成[0,3)之间的随机数 int main(){for (int i 0; i < 20; i) {switch (rand() % 3) {case 0:std::cout << "00" << std::endl;case 1:std::cout << "11&q…

MySQL 客户端命令

文章目录1、连接命令2、断开连接3、命令结束符4、查看所有数据库5、切换到指定数据库6、查看当前使用的数据库7、查看库中所有表8、查看所有用户9、执行SQL脚本10、查询当前时间1、连接命令 首先定位到MySQL安装根目录/bin目录下&#xff0c;然后执行如下命令&#xff1a; my…

SQL 库、表语句

文章目录一、数据库操作1、创建数据库2、删除数据库二、表操作1、创建表&#xff08;1&#xff09;主键&#xff08;primary key&#xff09;属性&#xff08;2&#xff09;unique属性&#xff08;3&#xff09;主键和unique约束的区别&#xff08;4&#xff09;外键&#xff0…

codeforces 69A-C语言解题报告

69A题目网址 题目解析 1.输入n个(x,y,z),当xi相加0;yi相加0;zi相加0同时时输出YES,否则输出NO 举例: 输入: 3 3 -1 7 -5 2 -4 2 -1 -3 输出: YES 2.注意点:使用二维数组去存放时,使用遍历行并对每一列分别相加 for(b0;b<n;b){count_xdir[b][0];count_ydir[b][1];count_z…

C++primer第十章 泛型算法 10.3 定制操作

10.3定制操作 很多算法都会比较输入序列中的元素。默认情况下&#xff0c;这类算法使用元素类型的&#xff1c;或运算符完成比较。标准库还为这些算法定义了额外的版本&#xff0c;允许我们提供自己定义的操作来代替默认运算符。例如&#xff0c;sort算法默认使用元素类型的&l…

SQL 查询语句

文章目录1、简单查询2、去除单列的重复结果查询3、去除多列的重复结果查询4、限制查询结果条数5、对查询结果排序&#xff08;1&#xff09;按照单个列的值进行排序&#xff08;2&#xff09;按照多个列的值进行排序6、带搜索条件查询&#xff08;1&#xff09;简单搜索条件查询…

2000年考研英语阅读理解文章一

文章详细讲解网址 注意点 1.文章开篇第一句话往往是文章所想要通过后面讲解的事情表达出来的最终观点 2.当询问到作者观点时,往往在最后一段,一般以下形式呈现: 1)few people …(这就是作者的观点) 2)I think 后面举什么别人所说的话,如果不是表达了赞同,则都是别人的观点,而…