vector的构造与内存管理

【STL序列式容器】剖析vector C++语言本身提供了一个序列式容器array,array是静态空间,一旦配置了就不能改变,类似于C语言的数组。 vector的数据安排以及操作方式与array很像,但vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。 阅读详情

1.vector的数据结构

template <class T, class Alloc = alloc>  
class vector {
...
protected:
  iterator start;                    //表示目前已使用空间的头
  iterator finish;				   //表示目前已使用空间的尾
iterator end_of_storage;         //表示目前可用空间的尾(已分配)
...
public:
  iterator begin() { return start; }
  const_iterator begin() const { return start; }
  iterator end() { return finish; }
  const_iterator end() const { return finish; }
  reverse_iterator rbegin() { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const { 
    return const_reverse_iterator(end()); 
  }
  reverse_iterator rend() { return reverse_iterator(begin()); }
  const_reverse_iterator rend() const { 
    return const_reverse_iterator(begin()); 
}
//求取已使用容量
  size_type size() const { return size_type(end() - begin()); }
  size_type max_size() const { return size_type(-1) / sizeof(T); }
  //求取目前可使用空间容量
  size_type capacity() const { return size_type(end_of_storage - begin()); }
  bool empty() const { return begin() == end(); }
...
}


 

2.vector的构造与内存管理

2.1初始化

容器的构造函数

1、C<T> c;   创建空容器

2、C c(c2);      创建c2的一个副本,C和c2必须有相同的容器类型及元素类型

3、C c(b,e);   创建c,其元素是迭代器b,e范围之间元素的副本。

       对于这一条,使用迭代器的时候,不要求容器类型相同。容器内的元素类型也可以不同,只要他们相互兼容,能够将要复制的元素转化为所构建的新容器的元素类型,即可以实现复制。

4、C c(n,t);   用n个值为t的元素创建容器c。(仅适用于顺序容器)。参数的顺序和语言相适应,n个t。

5、C c(n);    创建含n个默认值的容器c。(仅适用于顺序容器)。

 

       vector是顺序容器,所以上述5种构造函数都可以使用。

template <class T, class Alloc = alloc>  
class vector {
...
protected:
//vector缺省使用alloc作为空间配置器,并据此另外定义了一个data_allocator,为的是更方便以元素大小为配置单位
//专属空间配置器,每次配置一个元素大小
  typedef simple_alloc<value_type, Alloc> data_allocator;
...
  vector() : start(0), finish(0), end_of_storage(0) {}
  vector(size_type n, const T& value) { fill_initialize(n, value); }
  vector(int n, const T& value) { fill_initialize(n, value); }
  vector(long n, const T& value) { fill_initialize(n, value); }
  explicit vector(size_type n) { fill_initialize(n, T()); }
...
void fill_initialize(size_type n, const T& value) {
    start = allocate_and_fill(n, value);  //配置空间并设初值
    finish = start + n;					// 调整范围
    end_of_storage = finish; 			// 调整范围
  }
iterator allocate_and_fill(size_type n, const T& x) {
    iterator result = data_allocator::allocate(n); //配置n个元素空间
    __STL_TRY {
      // 全局函数,将result所指的未初始化空间设定为n个初值为x的变量
      // 定义于 <stl_uninitialized.h>。
      uninitialized_fill_n(result, n, x);  //全局函数
      return result;
    }


 

!!!uninitialized_fill_n()会根据第一参数的型别特性(type traits)决定使用算法fill_n()或反复调用construct()来完成任务。!!!

 

2.2 push_back()操作时vector内部的过程

    push_back()操作将新元素插入容器尾部,该函数首先检查是否还有备用空间(finish!=end_of_storage),如果有那么就直接在备用空间上构造元素,并调整迭代器finish。如果没有备用空间了(finish= end_of_storage),就扩充空间(重新配置,移动数据,释放原空间)。

 void push_back(const T& x) {
    if (finish != end_of_storage) {  // 还有备用空间
      construct(finish, x);   		// 直接在备用空间中构建元素
      ++finish;                          	// 调整范围
    }
    else                                  // 已无备用空间
      insert_aux(end(), x);			
  }

template <class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x) {
  if (finish != end_of_storage) {  // 还有备用空间
    // 在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值  
    construct(finish, *(finish - 1));
    ++finish;
    // 以下做啥用?
    T x_copy = x;
    copy_backward(position, finish - 2, finish - 1);
    *position = x_copy;
  }
  else {		// 已無備用空間
    const size_type old_size = size();//此时的size()等同于capacity()
    const size_type len = old_size != 0 ? 2 * old_size : 1;
    // 以上配置原则:如果原大小为0,那么则配置1(个元素大小)
    // 如果原大小不为0,那么配置原大小的2倍
    // 前半段用来放置原数据,后半段用来放置新数据

    iterator new_start = data_allocator::allocate(len); // 实际配置
    iterator new_finish = new_start;
    __STL_TRY {
      // 复制
      new_finish = uninitialized_copy(start, position, new_start);
      construct(new_finish, x);
      ++new_finish;
      // 将安插点的原内容页拷贝过来(该函数也可能被insert(p,x)调用)
      new_finish = uninitialized_copy(position, finish, new_finish);
    }
    catch(...) {
      // "commit or rollback"(如果不成功那么一个都不留)
      destroy(new_start, new_finish); 
      data_allocator::deallocate(new_start, len);
      throw;
    }

    // 解构并释放原vector
    destroy(begin(), end());
    deallocate();

    // 调整迭代器,指向新vector
    start = new_start;
    finish = new_finish;
    end_of_storage = new_start + len;
  }
}


 

        所谓的vector的大小的动态增长,并不是在原空间之后连续新空间(因为无法保证原空间之后尚有可供配置的空间)。而是以原来大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作一旦引起重新配置,指向原vector的所有迭代器就都失效了。这就是为什么《C++ Primer》中说push_back和inser可能会使迭代器失效的原因。其本质是:空间已进行重新配置。

 

 

 

STL学习笔记1(CArray与vector) 先做一个有趣的实验,测试一下CArray和vector添加数据的效率:结果(VS2005,release,默认优化O2):  可以看到,当需要添加大量数据时,CArray明显比vector慢。 测试代码:const int TEST_CASE_SIZE = 5;long len[TEST_CASE_SIZE]; 阅读详情

相关推荐

STL之vector的push_back过程详解

最近,被面试官的一道题问倒,很失落,明明看过《STL源码分析》,为啥这种问题还没答好,只能说自己看的时候没有仔细去思考。这道题就是标题的问题,面试完我重新看了一遍《STL源码分析》中关于这块的内容,这里记录下自己看完的一点理解。 在STL中,一般对容器的内存分配和构造是分开的2个过程,STL有专门的空间配置器负责分配内存,而构造则是通过placement new在已申请的内存上进行的,vecto...

cxc576502021的专栏 1万+

【C++】STL——vector的简单介绍、vector的定义、vector的构造函数声明、vector iterator的使用

STL、vector的含义、vector的使用、vector构造函数声明、vector iterator的使用、begin + end、rbegin + rend

Crocodile1006的博客 4749

SAP成本核算变式OKKN配置详解:从CK11N到CK24,手把手教你搞定标准成本发布

本文深入解析SAP成本核算变式OKKN的配置原理与实战应用,涵盖从CK11N到CK24的标准成本发布全流程。详细讲解数量结构控制、价值结构配置及间接费用计算规则,帮助成本会计精准掌握标准成本计算逻辑,解决BOM版本选择、工艺路线获取等常见问题,提升企业成本管理效率。

weixin_27219587的博客 284

STL vector的N种构造方式

1 使用默认无参的构造函数进行构造 vector intVect; 观察内存可以看到生成一个带有0个元素的vector时内存中_Myfirst _Mylast _Myend的值均为0,说明vector对象并没有在堆中分配任何存储空间,仅仅是在栈中分配了16字节存储vecotr对象元素,在这16字节中前4字节如果没猜错,应该是一个虚表指针。 Vecotr模版类有三个成员变量

伟的专栏 7276

Echats-wordcloud 文字云图的踩坑点【Unknown series wordCloud】

一直都是报 【ECharts Unknown series wordCloud】这玩意可能要刷脸,祝你好运吧~

Sky_Bug的博客 2417

DINOv3实战指南:如何利用零样本视觉模型革新工业质检

本文详细介绍了如何利用DINOv3零样本视觉模型革新工业质检流程。通过无需标注数据的自监督学习技术,DINOv3能快速部署高精度检测系统,显著降低成本和提升效率。文章涵盖模型选型、数据准备、实时检测优化及典型行业解决方案,为工业质检提供革命性AI实践指南。

ansible6ops的博客 120

C++ vector类

目录一.vector使用1.vector构造2.vector迭代器使用3.vector容量操作4.vector增删查改二.vector迭代器失效问题三.memcpy拷贝问题四.vector分部模拟实现 1.私有成员2.typedef3.3种构造函数4.拷贝构造、赋值运算符重载函数5.析构函数6.迭代器7.大小、容量8.reserve函数9.resize函数10.尾插、尾删函数11.下标运算符重载函数12.插入函数13.删除函数14.清理函数 五.vector类模拟实现总代码前言:vector类的学习,可以模

冰果滴的博客 5202

解决usbisp不识别无法烧录Atmega328P,Arduino不识别问题

如果使用Arduino IDE里面的烧录,可能会遇到一个问题,就是不识别国产这种廉价的USBISP 点击烧录引导程序,会遭遇到找不到USB设备的问题,选哪个都会提示找不到,比如选择USBasp could not find USB device with vid=0x16c0 pid=0x5dc vendor='www.fischl.de' product='USBasp' 因此,我们需要使用到progisp这一个软件的1.72版本 选择好芯片的型号后,调用编译好的HEX文...

arenascat的博客 7436

C++ vector容器-43-vector构造函数和赋值操作

在C++中常用的string的API都学习完了,这篇开始学习vector容器。vector有点类似数组,但是一个最懂扩容和支持尾部插入和删除的类似数组的容器。vector数据结构和数组非常相似,也称为单端数组,不同之处在于数组是静态空间,而vector可以动态扩容。 数组一旦创建了,就不可以改变,所以叫静态。也就是不可以给数组扩容,只能新建一个更大容量的数组。动态扩容不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。 1.vector构造函数 构造函数原型: .

Anthony_tester的博客 6842

YOLOv5实战:无人机巡检图片差异对比与违建标记(附完整代码)

本文详细介绍了如何利用YOLOv5目标检测技术实现无人机巡检图片差异对比与违建标记。通过图像对齐、目标检测、差异分析和可视化标记四个步骤,构建高效的违建识别系统,显著提升城市管理效率。文章包含完整代码实现和性能优化技巧,为计算机视觉在无人机巡检中的应用提供实用指南。

weixin_42535720的博客 280

当vCenter的证书过期、Root密码过期、Root密码遗忘同时发生时的解决方法与步骤

vCenter,强制修改root密码,修改SSO User密码,修复证书过期问题

OCTSJimmy的专栏 5546

【C++】vector的内存申请机制/内部存储原理

【C++】vector的内存申请机制/内部存储原理

m0_48086806的博客 2569

nbiot和2g_浅谈NBIOT

一、什么是NBIOT?1、概念窄带物联网(Narrow Band Internet of Things, NB-IoT),NB-IoT构建于蜂窝网络,只消耗大约180KHz的带宽,使用License频段,可采取带内、保护带或独立载波等三种部署方式,与现有网络共存。可直接部署于GSM网络、UMTS网络或LTE网络,以降低部署成本、实现平滑升级。2、NBIOT的特点和目标(1)超强覆盖:相对GPRS来...

weixin_39534100的博客 1704

C++ vector 内存管理需要注意的地方

vector内存管理

sukeman的博客 158

RK3576 Buildroot 双机 ADB 异常排障实录:同版 `boot.img`,一台可识别一台不可识别

进程在跑”不等于“USB 枚举成功”,adbd存活只是必要不充分条件。生产环境中的全局别名可能反向污染系统脚本。shell 命令替换中的字符串问题,必须做字节级验证(od -tx1相比“改环境规避”,核心脚本对输入做鲁棒处理更可长期维护。

小灰灰的博客 209

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【C++】理解vector的底层原理并模拟实现(手撕vector)

但是我们不仅要会用,还要理解它的底层原理,今天我们通过手撕一个自己的vector,来进一步加深对vector容器的理解。

谁在夜里看海.的博客 2300

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

vector内存管理机制详解

std::vector 是 C++ 标准库中最常用的动态数组容器,其内存管理机制是其高效性能的核心

weixin_40026739的博客 1171

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C++vector讲解

这篇文章分为两个部分讲解,一部分是,vector的使用;另一部分是,vector的模拟实现。

qq_54178958的博客 3759

C++核心编程(三十)容器(vector)

1)预留空间v.reserve(n);//预留空间中内存无法直接访问,不会自己初始化;2)区间构造将另一个vector的区间的值赋值个新创建的vector从而构造。4)拷贝构造将另外一个vector容器的值复制一份给新创建的vector。例2原理是检测容器首地址是否发生变化;预留空间可以减少内存动态扩展的次数。3)以化n个elem初始化构造。例1原理是检测容量是否变化。4)通过back函数访问。......

hpx12345678的博客 466

vector容器基础学习感悟

vector容器基础学习感悟自从学习了vector这个容器类,就深深的感觉到了它的实用性。 以下是个人的一些实用经验,如果有错的话,还望指正。template<typename T> explicit vector(); // 默认构造函数,vector对象为空 explicit vector(size_type n,

silen_ability的博客 427

深入理解与应用C++ Vector

带你具体剖析vector从底层到使用,成为vector高手

2301_77754590的博客 1881

vector模拟实现之构造函数初始化

vector的构造函数模拟实现,其中另外包含扩容函数reserve、尾插函数push_back的模拟实现

challenglistic的博客 1116

vector深入剖析

vectorvector的数据安排以及操作方式,与array非常的相似(这里的array是C和C++语言本身就有的,而不是在C11中引进在STL的std::array)。array是静态空间,一旦配置了就不能改变。vector是动态空间,随着元素的增加,它的内部机制会自行的扩充空间以容纳新元素。vector的构造 (1)vector<int>intVect;观察内存可以看到生成一个带有0个元素的v

qq_33620667的博客 493

emplace_back与push_back使用区别,move语义、与vector内存空间开辟弊端

当我们传递一个对象的参数给这两个函数时,分别由如下区别: emplace_back支持直接将构造函数所需的参数传递过去,然后构建一个新的对象出来,然后填充到容器尾部的。 push_back首先会利用传入的参数调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放入容器中。原来的临时变量释放。这样造成的问题就是临时变量申请资源的浪费。 #include <vector> #include <string> #include <iostream> using

Twoton的博客 3817

C++ Vector详细总结

在 c++ 中,vector 是一个十分有用的容器。它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。vector 是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。和 string 对象一样,标准库将负责管理与存储元素相关的内存。我们把 vector 称为容器,是因为它可以包含其他对象。一个容器中的所有对象都必须是同一种类型的。

wangzhening的博客 2万+
上一篇: vector的clear操作的内部过程
下一篇: 取样(算法)
sicofield
博客等级 码龄18年 169粉丝 169原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值