首页 > 编程语言 >C++的动态数组vector番外之capacity

C++的动态数组vector番外之capacity

时间:2024-08-23 17:22:22浏览次数:9  
标签:扩容 capacity string 番外 元素 C++ vector 内存

今日诗词:

爱他明月好,憔悴也相关。

西风多少恨,吹不散眉弯。

                                        ——《临江仙·寒柳》【清】纳兰容若


目录

引言

正文

string中的和vector中的capacity有什么区别

 vector扩容时内存分配的策略是什么?

capacity在vector中的表现如何

解析:

下期预告:C++容器之字符串的详解


引言:

看标题就知道我们今天要说的是capacity。其实我们之前在讲关于C++的(动态,静态)二维数组的补充那一章就提到过capacity,只不过当时是string的capacity,今天说的是vector中的capacity。那么两者的关系是增么样的,以及capacity的扩容规则是什么,还有就是在vector数组中的体现是什么,请看正文。

正文

string中的和vector中的capacity有什么区别

vector中的capacity和string中的capacity在概念上有相似之处,但也存在一些差异,主要体现在它们各自所属的数据结构和用途上。
1.共同点
容量定义:两者都表示容器在不重新分配内存的情况下能够存储的最大元素数量。即,capacity是容器预留的空间大小,用于存储元素,但并非所有预留的空间都已被实际使用。
获取方式:通过各自的成员函数capacity()来获取当前的容量值。
差异点
2.数据结构:
vector是C++标准模板库(STL)中的一个序列容器,用于存储元素的集合,这些元素可以是任意类型,并支持随机访问。
string同样是STL中的一个容器,但它专门用于存储字符序列,通常用于处理文本数据。在内部实现上,string可以被视为一种特殊的vector<char>,但它在操作字符序列时提供了更多的便利性和安全性。
3.扩容行为:
当vector的当前大小(size)等于其容量(capacity)时,如果继续添加新元素,vector会自动扩容,通常是通过分配一个更大的内存块并将旧元素复制到新块中来实现的。扩容的具体策略(如增长因子)可能因编译器和标准库实现而异。
string的扩容行为与vector类似,但在处理字符序列时可能有一些特定的优化。例如,某些string实现可能会使用短字符串优化(SSO),即对于较短的字符串,直接使用对象内部的存储空间来避免动态内存分配。
4.用途和特性:
vector因其灵活性和随机访问能力而被广泛用于需要动态数组的场景。
string则专门用于处理文本数据,提供了丰富的字符串操作函数,如拼接、查找、替换等,这些操作在vector中可能不那么直观或高效。
5.总结:
vector中的capacity和string中的capacity都表示容器预留的空间大小,用于存储元素。它们在概念上是相似的,但在具体的数据结构、扩容行为和用途上存在差异。vector更侧重于提供一个灵活的动态数组,而string则专注于高效地处理文本数据。


 vector扩容时内存分配的策略是什么?

vector扩容时内存分配的策略主要是基于其当前容量(capacity)和元素数量(size)来决定的,具体策略可能因不同的编译器和标准库实现而有所不同,但通常遵循以下原则:

1.增长因子:

当vector的当前容量不足以容纳新元素时,它会重新分配一块更大的内存空间。这块新空间的大小通常是原容量的一个倍数,这个倍数就是所谓的增长因子。常见的增长因子是2,意味着新容量通常是原容量的两倍。但也有其他可能的增长因子,如1.5倍,这取决于具体的实现和操作系统。

2.内存分配:

vector会分配一块足够大的新内存块,其大小至少能容纳当前所有元素加上即将添加的新元素。这块新内存块的大小由增长因子和当前容量共同决定。

3.元素复制/移动:

在分配了新的内存块之后,vector会将原内存块中的所有元素复制到新内存块中。这个复制过程可能通过元素的拷贝构造函数或移动构造函数来完成,具体取决于元素的类型和编译器的优化。

4.内存释放:

在元素复制完成后,vector会释放原来的内存块,以避免内存泄漏。

5.更新指针和容量:

最后,vector会更新其内部指针,使其指向新的内存块,并更新其容量值以反映新的内存块大小。

6.需要注意的是,虽然增长因子通常是2,但这不是一个固定的规则。不同的编译器和标准库实现可能会有不同的增长策略。此外,由于内存分配和释放的开销,频繁地扩容可能会对性能产生负面影响。因此,在可能的情况下,建议使用reserve()成员函数来预先分配足够的内存空间,以减少扩容的次数并提高程序的性能。总的来说,vector扩容时内存分配的策略是灵活的,旨在平衡内存使用效率和程序性能之间的关系。


capacity在vector中的表现如何

这里我们依然借用一下上期内容的代码来说明:C++的动态数组vector

include<iostream>
include<vector>
using namespace std;
int main()
{
//创建动态数组
vector<int>v={1,2,3,4};
cout<<"size is"<<v.size()<<endl;
cout<<"capacity is"<<v.capacity()<<endl;
//遍历所有元素
for(int i=0;i<v.size();++i)
{
  cout<<v[i]<<endl;
}
 
//在尾部插入一个元素
v.push_back(5);
cout<<"size is"<<v.size()<<endl;
cout<<"capacity is"<<v.capacity()<<endl;
//遍历所有元素
for(int i=0;i<v.size();++i)
{
  cout<<v[i]<<endl;
}
 
//在尾部任意位置插入一个元素
v.insert(--v.end(),6);
cout<<"size is"<<v.size()<<endl;
cout<<"capacity is"<<v.capacity()<<endl;
//遍历所有元素
for(int i=0;i<v.size();++i)
{
  cout<<v[i]<<endl;
}
 
//在尾部移除一个元素
v.pop_back();
cout<<"size is"<<v.size()<<endl;
cout<<"capacity is"<<v.capacity()<<endl;
//遍历所有元素
for(int i=0;i<v.size();++i)
{
  cout<<v[i]<<endl;
}
 
//在尾部移除一个元素
v.erase(v.end()-1);
cout<<"size is"<<v.size()<<endl;
cout<<"capacity is"<<v.capacity()<<endl;
//遍历所有元素
for(int i=0;i<v.size();++i)
{
  cout<<v[i]<<endl;
}
 
return 0;
} 

 

 大家看上面的两张黑框框,这个就是cout的窗口,我们现在对照着代码和图片的结果观察。

解析:

一开始我们定义的vector数组的内容大小是4,预存储的大小也是4,这是因为我们的初始化的影响。然后我们在尾部添加一个元素,这是再看内容大小是5,预存储大小是6。这是因为我们添加了一个元素,导致vector数组自动的扩容,从而预存储大小变大。我们上面说到vector的扩容是按倍数来扩容的,这里的6就是4的1.5倍大小。然后我们在数组任意位置再插入一个数组,这时我们的内容大小变大到6,预存储大小不变(因为·够用,所以不会再变化)。之后的连着两次的删除元素都只会导致内容的大小变化(变小),预存储的大小不变,这是因为编译器以防万一,害怕内存不够用的机制。

这就是vector中的capacity的各种方面的体现。我们只有理解了这些基本的原理才会让我们在以后的C++道路上越来越通畅。


标签:扩容,capacity,string,番外,元素,C++,vector,内存
From: https://blog.csdn.net/2301_81280642/article/details/141469137

相关文章

  • 在C#中调用C++dll
        一、C++函数中的double**参数C++DLL中的接口如下:intgray2energy(double**data,constintlength,constdoublegamma);在C#中调用C++:方式1,通过指针的方式在C#也用double**对应C++中的double**[DllImport("xxxx.dll",CallingConvention=CallingConven......
  • 小朋友学C++-题集
    小朋友学C++参考c语言基础啊哈C语言书籍算法图解-python.pdfc语言教程在线C++/C/python编译器C语言基础==========================C语言精读100例!!!!C语言实验指导与习题解答小项目学习扫雷小游戏贪吃蛇小游戏学生成绩管理系统图书管理系统小说分析软件第一章,与......
  • C++ (病毒代码) (3)
    所有都可以,亲自尝试   第2个不要怕,只会关机!一切都可以用  ALT+F4  结束运行窗口即可解决!!! 1.鼠标乱飞 #include<windows.h>#include<ctime>usingnamespacestd;intmain(){   Sleep(1000);   intx=GetSystemMetrics(SM_CXSCREEN);   ......
  • C++ 打字游戏 (1)
    好玩!!!!!!!!!!!#include<iostream>#include<windows.h>#include<conio.h>usingnamespacestd;floatscore;intblue,yellow,use=1;intmain(){   system("title打字练习");   for(;;)   {      system("cls");   ......
  • C++基础
    C++面向对象编程的四大特性:封装:封装是隐藏对象的属性和实现细节,仅对外公开接口,控制程序对类属性的读取和修改。良好的分装能减少耦合,同时隐藏实现细节。抽象:抽象包括数据抽象和过程抽象。数据抽象关注于目标的特性信息,过程抽象关注于目标的功能是什么,而不是功能怎么实现。继承......
  • C/C++语言基础--字符串(包括字符串与字符数组、字符串与指针、字符串处理函数等),代码
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言无论什么语言,字符串都是最重要、最基础的数据类型,他对二进制有很好的对应关系在C语言中没有提供专门的处理字符串的类型,但是我们可以通过字符数组、开辟内存地址来处理字符串本文将从字符串与字符数组的关系、字符......
  • C++:虚函数和虚表详细总结
    一、虚函数(VirtualFunctions)1.定义虚函数是基类中使用virtual关键字声明的成员函数,支持动态多态性。通过基类指针或引用调用虚函数时,会根据实际对象类型选择调用相应的函数实现。2.声明和定义虚函数的声明:classBase{public:virtualvoidshow();//......
  • c++ chrono头文件内Duration 、time_point和Clock
    前言        http://t.csdnimg.cn/eprLZ中介绍了关于chrono的基本操作,本文来介绍chrono与其他类的关系。内容Duration    duration表示一段时间间隔template<classRep,classPeriod=std::ratio<1>>classduration        Rep表示持续时......
  • C++基础 — 数组学习
    目录一、概述二、一维数组1.一维数组定义方式2.一维数组数组名二、二维数组1.二维数组定义方式2.二维数组数组名一、概述所谓数组,就是一个集合,里面存放了相同类型的数据元素。特点1:数组中的每个数据元素都是相同的数据类型;特点2:数组是由连续的内存位置组成的。二、......
  • C++入门基础知识29
    成长路上不孤单......