很多初学者分不清楚 vector 容器的容量(capacity)和大小(size)之间的区别,甚至有人认为它们表达的是一个意思。本节将对 vector 容量和大小各自的含义做一个详细的介绍。

vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数。

对于一个 vector 对象来说,通过该模板类提供的 capacity() 成员函数,可以获得当前容器的容量;通过 size() 成员函数,可以获得容器当前的大小。例如:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. std::vector<int>value{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
  7. value.reserve(20);
  8. cout << "value 容量是:" << value.capacity() << endl;
  9. cout << "value 大小是:" << value.size() << endl;
  10. return 0;
  11. }

程序输出结果为:

value 容量是:20
value 大小是:15

结合该程序的输出结果,图 1 可以更好的说明 vector 容器容量和大小之间的关系。


图 1 vector 容量和大小的区别

显然,vector 容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。注意,这里的“更多”并不是 1 个。换句话说,当 vector 容器的大小和容量相等时,如果再向其添加(或者插入)一个元素,vector 往往会申请多个存储空间,而不仅仅只申请 1 个。

一旦 vector 容器的内存被重新分配,则和 vector 容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。

举个例子:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int>value{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
  7. cout << "value 容量是:" << value.capacity() << endl;
  8. cout << "value 大小是:" << value.size() << endl;
  9. printf("value首地址:%p\n", value.data());
  10. value.push_back(53);
  11. cout << "value 容量是(2):" << value.capacity() << endl;
  12. cout << "value 大小是(2):" << value.size() << endl;
  13. printf("value首地址: %p", value.data());
  14. return 0;
  15. }

运行结果为:

value 容量是:15
value 大小是:15
value首地址:01254D40
value 容量是(2):22
value 大小是(2):16
value首地址: 01254E80

可以看到,向“已满”的 vector 容器再添加一个元素,整个 value 容器的存储位置发生了改变,同时 vector 会一次性申请多个存储空间(具体多少,取决于底层算法的实现)。这样做的好处是,可以很大程度上减少 vector 申请空间的次数,当后续再添加元素时,就可以节省申请空间耗费的时间。

因此,对于 vector 容器而言,当增加新的元素时,有可能很快完成(即直接存在预留空间中);也有可能会慢一些(扩容之后再放新元素)。

修改vector容器的容量和大小

另外,通过前面的学习我们知道,可以调用 reserve() 成员函数来增加容器的容量(但并不会改变存储元素的个数);而通过调用成员函数 resize() 可以改变容器的大小,并且该函数也可能会导致 vector 容器容量的增加。比如说:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int>value{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
  7. cout << "value 容量是:" << value.capacity() << endl;
  8. cout << "value 大小是:" << value.size() << endl;
  9. value.reserve(20);
  10. cout << "value 容量是(2):" << value.capacity() << endl;
  11. cout << "value 大小是(2):" << value.size() << endl;
  12. //将元素个数改变为 21 个,所以会增加 6 个默认初始化的元素
  13. value.resize(21);
  14. //将元素个数改变为 21 个,新增加的 6 个元素默认值为 99。
  15. //value.resize(21,99);
  16. //当需要减小容器的大小时,会移除多余的元素。
  17. //value.resize(20);
  18. cout << "value 容量是(3):" << value.capacity() << endl;
  19. cout << "value 大小是(3):" << value.size() << endl;
  20. return 0;
  21. }

运行结果为:

value 容量是:15
value 大小是:15
value 容量是(2):20
value 大小是(2):15
value 容量是(3):30
value 大小是(3):21

程序中给出了关于 resize() 成员函数的 3 种不同的用法,有兴趣的读者可自行查看不同用法的运行结果。

可以看到,仅通过 reserve() 成员函数增加 value 容器的容量,其大小并没有改变;但通过 resize() 成员函数改变 value 容器的大小,它的容量可能会发生改变。另外需要注意的是,通过 resize() 成员函数减少容器的大小(多余的元素会直接被删除),不会影响容器的容量。

vector容器容量和大小的数据类型

在实际场景中,我们可能需要将容器的容量和大小保存在变量中,要知道 vector<T> 对象的容量和大小类型都是 vector<T>::size_type 类型。因此,当定义一个变量去保存这些值时,可以如下所示:

  1. vector<int>::size_type cap = value.capacity();
  2. vector<int>::size_type size = value.size();

size_type 类型是定义在由 vector 类模板生成的 vecotr 类中的,它表示的真实类型和操作系统有关,在 32 位架构下普遍表示的是 unsigned int 类型,而在 64 位架构下普通表示 unsigned long 类型。

当然,我们还可以使用 auto 关键字代替 vector<int>::size_type,比如:

  1. auto cap = value.capacity();
  2. auto size = value.size();

C++ STL vector容量(capacity)和大小(size)的区别的更多相关文章

  1. C++STL——vector类

    vector容器 1.1 vector容器的基本概念 Array 是静态空间,一旦配置了就不能改变,要换大一点或者小一 点的空间,可以,一切琐碎得由自己来,首先配置一块新的空间,然后将旧空间的 数据搬 ...

  2. C++ STL vector(向量容器)的使用(附完整程序代码)

    一.简单介绍 Vectors 包括着一系列连续存储的元素,其行为和数组类似. 訪问Vector中的随意元素或从末尾加入元素都能够在O(1)内完毕,而查找特定值的元素所处的位置或是在Vector中插入元 ...

  3. STL—Vector简介

    有关C++ STL 中的vector向量的用法(代码示例) 一. 简介 Vector是一个称为向量的顺序容器(不明白顺序容器与关联容器的可以Google). 二. 特点 1. 动态(相当于一个动态数组 ...

  4. STL vector用法介绍

    STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和f ...

  5. C++ STL vector 内存分配

    vector为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储. 当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间.拷贝元素.撤销 ...

  6. STL vector 用法介绍

    介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...

  7. STL vector使用方法介绍

    介绍 这篇文章的目的是为了介绍std::vector,怎样恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...

  8. stl——vector详解

    stl——vector详解 stl——vector是应用最广泛的一种容器,类似于array,都将数据存储于连续空间中,支持随机访问.相对于array,vector对空间应用十分方便.高效,迭代器使ve ...

  9. C++STL vector详解(杂谈)

    介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...

随机推荐

  1. Bug搬运工-CSCvi02106 :Cisco 2800, 3800, 1560 APs: when connected to a Cisco Switch CDP-4-DUPLEX_MISMATCH log is seen

    Cisco 2800, 3800, 1560 APs: when connected to a Cisco Switch CDP-4-DUPLEX_MISMATCH log is seen CSCvi ...

  2. 【C语言】输入圆的半径,求解圆的周长和面积

    公式: C=2πr S=πr² 代码: #include<stdio.h> int main() { float r,PI; PI = 3.14159; printf("请输入圆 ...

  3. 巧用命令行工具 redis-cli

    我们天天都在使用 Redis 内置的命令行工具 redis-cli,久而久之以为它就是一个简单的交互式 Redis 数据结构手工操作程序,但是它背后强大的功能绝大多数同学可能闻所未闻.本节我们一起来挖 ...

  4. rapidxml编写xml文件(一)

    int writeXML(void) { rapidxml::xml_document<> doc; rapidxml::xml_node<> *rot = doc.alloc ...

  5. 鸡汤 - Choice is yours

    传送门 https://kamranahmed.info/blog/2018/03/24/choice-is-yours/ Our whole lives are driven by the choi ...

  6. 「题解」「POJ1322」Chocolate

    目录 题目 原题目 简易题意 思路分析 代码 练习题 题目 原题目 点这里 简易题意 包裹里有无限个分布均匀且刚好 \(c\) 种颜色的巧克力,现在要依次拿 \(n\) 个出来放到桌子上.每次如果桌子 ...

  7. Spring Boot Ftp Client 客户端示例支持断点续传

    本章介绍 Spring Boot 整合 Ftpclient 的示例,支持断点续传 本项目源码下载 1 新建 Spring Boot Maven 示例工程项目 注意:是用来 IDEA 开发工具 File ...

  8. Intellij IDEA中创建Package变成一级目录

    1.创建包,但是出来的却是一级目录 2.因为Compact Middle Packages默认勾选上了,取消掉即可

  9. 转专业后补修C语言的一些体会(3)

    1.指针:指针是C语言最为强大的工具之一,有着很多优点,比如可以改善子程序的效率,为动态数据结构提供支持,为C的动态内存分配系统提供支持,为函数提供修改变量值的手段.但指针的使用十分困难.会出现很多意 ...

  10. [ DLPytorch ] word2vec&词嵌入

    word2vec WordEmbedding 对词汇进行多维度的描述,形成一个密集的矩阵.这样每两个词之间的相似性可以通过进行内积的大小体现出来.越大说明距离越远,则越不相似. Analogies(类 ...