在百度上做网站推广怎么弄/网络营销工具有哪些
✍作者:阿润菜菜
📖专栏:C++
vector的常用接口
首先贴上:vector的文档介绍,以备查阅使用。
vector的基本框架:
vector的成员变量分别是空间首部分的_start指针和最后一个元素的下一个位置的_finish指针,以及指向可用空间末尾的下一个位置的_end_of_storage指针,对于vector来说,它的底层就是由顺序表实现的,所以它的迭代器就是原生指针T*,我们定义const和非const的迭代器,便于const和非const对象的迭代器的调用。
vector的构造函数
vector提供四种构造函数来进行初始化:
1.对于无参构造,我们利用初始化列表来进行初始化,用nullptr初始化
vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr)
{}
2.构造并初始化是用n个value值来初始化,因为value既可能是内置类型,也可能是自定义类型,所以如果用引用作参数的话,需要用const引用,也就是常引用来作参数,否则无法接收内置类型的实参。
//vector<int> v(10,5)初始化vector(size_t n, const T& val = T()) //这里调用匿名对象的默认构造初始化{reserve(n);for (size_t i = 0; i < n; ++i){push_back(val); //进行深拷贝,不要用memcpy,浅拷贝会带来二次析构等问题}}
注意匿名对象的生命周期只有其所在那一行,const引用会延长匿名对象的生命周期到引用对象域结束,因为后续调用就是匿名对象,并自动销毁
在实现完n个value构造的构造函数之后,如果我们此时用10个int类型的数字1来构造对象v1,实际会报错,报错的原因其实是由于函数的匹配优先级所导致的实参无法正确匹配相应的构造函数。而使用10个char类型的字符A却不会报错,这是由于函数的匹配优先级决定的
对于这种问题STL源码的解决方式是利用了函数重载来解决了这个问题,多重载了一个类型为int的构造函数
//int 不能向size_t 类型转换vector(int n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; ++i){push_back(val);}}
3.对于拷贝构造函数的实现有个一定需要注意的问题: 深浅拷贝问题 — 对象嵌套深浅拷贝问题。
我们传统写法会是memcpy申请资源并按字节拷贝,这种写法用在string类实现可以,但在vector类实现就肯定不行了,因为vector的模板实例化有int数组对象,string对象、及vector的vector嵌套等等。所以对于自定义类型如果时浅拷贝,会使两个对象指向同一块空间,对象调用析构函数时会造成二次析构!值拷贝很多时候是一种危险的行为。
我们采用现代写法,也就是复用写法,利用形参对象v的迭代器来构造临时对象tmp,然后将对象tmp和* this进行交换,这里交换函数需要我们自己提供,复用库里的swap即可。同时为了防止对象tmp离开函数栈帧销毁时造成野指针的访问问题,所以在调用构造函数时采用了初始化列表的方式将* this的三个成员都初始化为nullptr。
在实现拷贝构造后,我们还需要实现赋值重载,利用传值拷贝构造的临时对象即可,然后调用swap类成员函数即可完成自定义类型的赋值工作。为了符合连续赋值含义,我们利用引用来作为返回值。
vector& swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);return *this;
}vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{//复用区间构造vector<T> tmp(v.begin(), v.end());swap(tmp);//交换的时候就可以体现出拷贝构造函数初始化列表的好处了
}// v1 = v2;
// v1 = v1;
vector<T>& operator=(vector<T> v)//返回引用,符合连续赋值的含义
{swap(v);return *this;
}
不复用swap函数,通过复用reserve函数实现,要注意更新_finish和_endofstorge
vector(const vector<T>& v): _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){reserve(v.capacity());iterator it = begin();const_iterator vit = v.cbegin();while (vit != v.cend()){*it++ = *vit++;}_finish = _start + v.size();_endOfStorage = _start + v.capacity();}
小tips:在拷贝构造函数,可以不加模板参数 为了可读性我们推荐加上
4.迭代器区间构造
vector的迭代器区间初始化是个模板 可以传入任意类型,并可以部分初始化,但实际上vector很少用迭代器。
template<class InputIterator>vector(InputIterator first, InputIterator last){reserve(last - first);while (first != last){push_back(*first);++first;}}
vector iterator — 迭代器
接口 | 说明 |
---|---|
begin + end | 获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin + rend | 获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator |
vector 空间函数
1.capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。
不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL
测试代码
// 测试vector的默认扩容机制
void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i) {v.push_back(i);if (sz != v.capacity()) {sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}
2.reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题,提高效率。
resize在开空间的同时还会进行初始化,影响size。
reserve函数
1.对于reserve以及resize函数来说,官方并没有将其设定为能够实际缩容的功能,明确规定这个函数在其他情况下,例如预留空间要比当前小的情况下,这个函数的调用是不会引起空间的重新分配的,也就是说容器vector的实际开辟的capacity是不会被影响的。值得注意的是缩容表面看起来是降低了空间的使用率,想要提高程序的效率,但实际上并未提高效率,缩容是需要异地缩容的,需要重新开空间和拷贝数据,代价不小,所以不建议对空间进行缩容
2.shrink_to_fit就是缩容函数,强制性的将capacity的大小降低到适配size大小的值,它的设计理念就是以空间来换时间,但日常人们所使用的手机或者PC空间实际上是足够的,不够的是时间,所以这种函数还是不要使用的为好,除非说你后面肯定不会插入数据了,不再进行任何modify操作,那你可以试着将空间还给操作系统,减少空间的使用率
//开辟空间void reserve(size_t n){if (n > capacity()) //先检查,避免缩容//如果大于原有空间,则重新开辟并挪动数据,否则就不做任何行为{size_t sz = size();T* tmp = new T[n]; //开辟失败会抛异常if (_start){memcpy(tmp, _start, , sizeof(T) * size());//拷贝旧数据delete[] _start;}//更新_start = tmp;_finish = _start + sz;_end_of_storage = _start + n;}}
resize函数
1.注意C++是泛型编程的,所以resize提供了参数 T val = T () 用匿名对象默认构造来初始化
//调整空间和初始化void resize(size_t n; T val = T()) //泛型编程 --- T val = T() 即用匿名对象的默认构造来初始化{if (n < size()) //若小于原空间数据量{//删除数据,但并不实际上缩小空间_finish = _start + n;}else{if (n > capacity()){reserve(n);}while (_finish != _start + n){*_finish = val;++_finish;}}}
vector 增删查改
1.这里push_back和pop_back都是对insert和erase的复用,所以我们主要介绍三个函数的模拟实现。find函数我们无需提供,直接调用算法模块库里的,对于swap我们需要直接实现,因为我们是一个自定义类型,浅拷贝无法实现swap。同时在实现insert和erase函数是我们会遇到第一个经典的迭代器失效问题,就是因为扩容操作,造成了迭代器野指针问题。
insert函数
1.在insert函数模拟实现中,因为插入数据,很多时候我们要对空间扩容,而且基本上是异地扩容,在扩容后迭代器pos指针就会指向已释放的空间,造成了野指针访问的问题,解决就是:更新pos迭代器指针
我们提供返回值 返回pos(使用时需要pos 接受返回值更新pos迭代器指针)
2.而且vector的插入操作如果导致底层空间重新开辟,则迭代器就会失效。如果空间足够,那么迭代也算失效了,因为数据相对位置已经发生改变,他已经不是指向之前的位置了。
3.那我们为什么不能用引用传参, 注意所有的传值返回都是拷贝临时对象,具有常性(不能改变),不能传给左值引用
iterator insert(iterator pos, const T& val){assert(pos >= _start);assert(pos <= _finish);if (_finish == _end_of_storage) //检查扩容{size_t len = pos - _start; //记录len 后续pos更新reserve(capacity() == 0 ? 4 : capacity() * 2);//扩容后更新pos,解决迭代器pos失效问题pos = _start + len;}iterator end = _finish - 1;while (end >= pos) //遍历挪动数据{*(end + 1) = *end;--end;}*pos = val;++_finish;return pos;}
erase函数
1.erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。
2. 在实现函数erase时,erase 之后,认为pos是否失效? 我们认为失效,不要访问,因为行为结果不能确定的,根据具体的编译器实现有关系 ---- 本质是不让pos跳过_finish(本该访问数据) 发生段错误或者结果不对
3. 在使用时,vector 的erase 要配合find实现
vs编译器会进行强制检查,erase以后的迭代器,都不能继续访问
// 返回删除数据的下一个数据// 方便解决:一边遍历一边删除的迭代器失效问题iterator erase(Iterator pos){// 挪动数据进行删除iterator begin = pos + 1;while (begin != _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;}
operator[ ]
1.其实vector一般不常用迭代器。常用的stl只有 string和vector 会使用方括号,其他的都会使用迭代器
2.我们要注意越界访问的检查机制,直接断言assert(pos<size)
//[]T& operator [] (size_t pos){assert(pos <= size());return _start[pos];}const T& operator [] (size_t pos) const{assert(pos <= size());return _start[pos];}
附上:vector模拟实现源码
vector深度剖析
使用memcpy拷贝问题
- memcpy是内存的二进制格式按字节拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中。这是一种妥妥浅拷贝
- 如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且
自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝,会造成对象和拷贝对象指向同一块空间,在调用析构时,会二次析构。
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是
浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
迭代器失效问题
1.vector的迭代器是一个原生指针的typedef,所以迭代器失效的本质就是指针失效,换句话说就是野指针访问,对指针指向的无效空间进行访问所导致的问题。
2.在使用insert时,我们需要传某个位置的迭代器,如果在insert中不发生扩容,则这个迭代器在insert之后还是有效的,但只要在insert中发生扩容,则迭代器就会失效,因为reserve进行的是异地扩容,所以原有的迭代器就不能使用,因为原有迭代器指向的是已经释放的旧空间的某个位置,所以如果继续使用,则势必会发生野指针的访问,这正是我们所说的迭代器失效。
3.比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的
空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,
程序可能会崩溃)
4.对于vector可能会导致其迭代器失效的操作有:会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。
迭代器失效解决办法:在使用前,对迭代器重新赋值即可
vector二维数组
构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类型的,每行没有包含任何元素,如果n为5时如下所示:
vv中元素填充完成之后,如下图所示:
使用标准库中vector构建动态二维数组时与上图实际是一致的.
相关文章:

【STL】Vector剖析及模拟实现
✍作者:阿润菜菜 📖专栏:C vector的常用接口 首先贴上:vector的文档介绍,以备查阅使用。 vector的基本框架: vector的成员变量分别是空间首部分的_start指针和最后一个元素的下一个位置的_finish指针,以…...

数据库建表的一些技巧
文章目录 1.名字1.1 见名知意1.2 大小写1.3 分隔符1.4 表名1.5 字段名称1.6 索引名2.字段类型3.字段长度4.字段个数5. 主键6.存储引擎7. NOT NULL8.外键9. 索引10.时间字段11.金额字段12.唯一索引13.字符集14. 排序规则15.大字段总结如果我们在建表的时候不注意细节,等后面系统…...

线程(一)
线程 1. 线程 定义:线程是进程的组成部分,不同的线程执行不同的任务,不同的功能模块,同时线程使用的资源师由进程管理,主要分配CPU和内存。 在进程中,线程执行的方式是抢占式执行操作,需要考…...

[深入理解SSD系列 闪存实战2.1.8] NAND FLASH Multi Plane Program(写)操作_multi plane 为何能提高闪存速度
前言 上一篇我们介绍了 [深入理解SSD系列 闪存实战2.1.7] NAND FLASH基本编程(写)操作及原理_NAND FLASH Program Operation 源码实现。这只是一次对单个plane 写, 按这样的话, 要先program plane 0 完成后, 再 program plane 1。 如果我偷偷告诉你, 两个 plane 可以一起…...

计算机网络(第八版)——第一章知识总结
本笔记来源于博主上课所记笔记整理,可能不全,欢迎大家批评指正,如果觉得有用记得点个赞,给博主点个关注...该笔记将会持续更新...整理不易,希望大家多多点赞。 第一章 计算机网络体系结构 1.计算机网络的作用 1.1互…...

Linux学习笔记
前段时间看了网课:https://www.bilibili.com/video/BV1mW411i7Qf?spm_id_from333.337.search-card.all.click&vd_source7b9f1ca2783a4c39a4d640a31e23457e 记了一些笔记,先放到这里,后面慢慢整理: 内存分配:分区…...

树与二叉树(概念篇)
树与二叉树1 树的概念1.1 树的简单概念1.2 树的概念名词1.3 树的相关表示2 二叉树的概念2.1 二叉树的简单概念2.1.1 特殊二叉树2.2 二叉树的性质2.3 二叉树的存储结构1 树的概念 1.1 树的简单概念 树是一种非线性的数据结构,它是由n(n>0)个有限节点组成的一个具…...

C++回顾(二十五)—— map/multimap容器
25.1 map/multimap的简介 map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。map的…...

7.3 向量的数量积与向量积
🙌作者简介:数学与计算机科学学院出身、在职高校高等数学专任教师,分享学习经验、生活、 努力成为像代码一样有逻辑的人! 🌙个人主页:阿芒的主页 ⭐ 高等数学专栏介绍:本专栏系统地梳理高等数学…...

Qt静态扫描(命令行操作)
Qt静态扫描(命令行操作) 前沿: 静态代码分析是指无需运行被测代码,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌…...

【Hadoop】配置文件
Hadoop 配置文件分两类:默认配置文件和自定义配置文件,只有用户想修改某一默认 配置值时,才需要修改自定义配置文件,更改相应属性值 (1)默认配置文件: cd $HADOOP_HOME/share/hadoop common路…...

python进程池
Python进程池是Python标准库中multiprocessing模块提供的一种用于管理进程的方式。它可以使Python程序以并行的方式执行任务,提高程序的运行效率。本篇博客将介绍如何使用Python进程池。 创建进程池 在使用Python进程池之前,我们需要先创建一个进程池对…...

笔记本固态盘数据丢失怎么办?笔记本固态盘怎么恢复数据
如果笔记本固态盘数据丢失怎么办?笔记本固态盘怎么恢复数据?下面将为大家详细地介绍一下笔记本固态硬盘数据恢复的三种实用方法,希望对大家有所帮助。一、简单恢复方法笔记本固态硬盘数据删除以后,较为简单直接的恢复方法就是从回…...

堆的结构与实现
堆的结构与实现二叉树的顺序结构堆的概念及结构堆的实现堆的创建向上调整建堆向下调整建堆堆的操作链接二叉树的顺序结构 堆其实是具有一定规则限制的完全二叉树。 普通的二叉树是不太适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树会更适合使用顺…...

Pandas快速入门
Pandas是Python中非常流行的数据处理库之一,它提供了一种简单而强大的方法来处理和分析数据。在本篇文章中,我将向你介绍Pandas的基础知识,以便你可以开始使用它来处理和分析数据。 安装Pandas 首先,你需要安装Pandas。可以通过…...

LVGL学习笔记18 - 表Table
目录 1. Parts 1.1 LV_PART_MAIN 1.2 LV_PART_ITEMS 2. 样式 2.1 设置行列数 2.2 设置单元格字符串 2.3 设置单元格宽度 2.4 设置表格高度和宽度 2.5 设置字符串颜色 2.6 设置边框颜色 2.7 设置背景颜色 3. 事件 4. CELL CTRL 表格是由包含文本的行、列和单元格构…...

嵌入式安防监控项目——html框架分析和环境信息刷新到网页
目录 一、html控制LED 二、模拟数据上传到html 一、html控制LED 简单来说就是html给boa服务器发了一个控制指令信息,然后boa转发给cgi进程,cgi通过消息队列和主进程通信。主进程再去启动LED子线程。 这是老师给的工程。 以前学32都有这工具那工具来管…...

centos安装docker详细步骤
目录 一.前言 1.环境要求2.官网中文安装参考手册 二.安装步骤 1.卸载旧版本2.安装需要的软件包3.设置docker镜像源 1.配置docker镜像源 方式1:官网地址(外国):方式2:阿里云源:2.查看配置是否成功 4.更新yum软件包索引5.可以查看…...

初识HTML、W3C标准、如何利用IDEA创建HTML项目、HTML基本结构、网页基本信息
一、什么是HTML? HTML——Hyper Text Markup Languagr(超文本标记语言) 超文本包括:文字、图片、音频、视频、动画等 目前网页中常用——HTML5 HTML5提供了一些新的元素和一些有趣的新特性,同时也建立了一些新的规则…...

为什么程序员喜欢这些键盘?
文章目录程序员的爱介绍个人体验程序员的爱 程序员是长时间使用计算机的群体,他们需要一款高品质的键盘来保证舒适的打字体验和提高工作效率。在键盘市场上,有很多不同类型的键盘,但是对于程序员来说,机械键盘是他们最钟爱的选择…...

JS中数组去重的几种方法
JS 中有多种方法可以实现数组去重,下面是几种常用的方法:1、使用 Set 去重:Set 数据结构中不能有重复元素,可以将数组转成 Set 类型,再转回数组。let arr [1,2,3,4,5,6,2,3,4]; let uniqueArr [...new Set(arr)]; co…...

Nginx 配置实例-负载均衡
一、实现效果 浏览器地址栏输入地址 http://192.168.137.129/edu/a.html,负载均衡效果,将请求平均分配到8080和8081两台服务器上。 二、准备工作 1. 准备两台tomcat服务器,一台8080,一台8081 (具体操作如下两个链接) Nginx配置实…...

引出生命周期、生命周期_挂载流程、生命周期_更新流程、生命周期_销毁流程、生命周期_总结——Vue
目录 一、引出生命周期 二、生命周期_挂载流程 三、生命周期_更新流程 四、生命周期_销毁流程 五、生命周期_总结 一、引出生命周期 生命周期: 1.又名:生命周期回调函数、生命周期函数、生命周期钩子。 2.是什么:Vue在关键时刻帮我们调…...

C++ STL学习之【vector的使用】
✨个人主页: Yohifo 🎉所属专栏: C修行之路 🎊每篇一句: 图片来源 The power of imagination makes us infinite. 想象力的力量使我们无限。 文章目录📘前言📘正文1、默认成员函数1.1、默认构造…...

方差分析与单因素方差分析
研究分类型自变量对数值型因变量的影响。检验统计的设定和检验方法与变量间的方差是否相等有关。 例如研究行业、服务等级对投诉数的影响:如表格中给出4个行业、每个行业有3个服务等级、样本容量为7、观测值为投诉数。则构成一个3维的矩阵。 在上述基础上…...

分布式链路追踪组件skywalking介绍
SkyWalking组件概念 一个开源的可观测平台, 用于从服务和云原生基础设施收集, 分析, 聚合及可视化数据。SkyWalking 提供了一种简便的方式来清晰地观测分布式系统, 甚至横跨多个云平台。SkyWalking 更是一个现代化的应用程序性能监控(Application Performance Monitoring)系统…...

SUBMIT的用法
SUBMIT的用法 一、简介 系统MB52/MB51/MB5B等类似的报表 ,虽然数据很全面,执行效率也够快,但是经常会不满足用户需求(增添字段、添加查询条件等),很多ABAP 会选择去COPY出标准程序,然后去做修改…...

网页基本标签、图像标签、链接标签、块内元素和块元素、列表标签、表格标签
一、网页基本标签 标题标签 段落标签 未写段落标签前,文本没有按照想要的格式排列显示 写段落标签后: 每句都是一段,所以句与句距离比较宽 换行标签 同一段,只是把文字换行,所以比较紧凑 水平线标签 字体样式标签 …...

RxJava操作符变换过程
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0我们在使用rxjava的操作符时都觉得很方便,但是rxjava是怎么实现操作符的转换呢࿰…...

开放平台订单接口
custom-自定义API操作 注册开通 taobao.custom 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中) secret String 是 调用密钥 api_name String 是 API接口名称(包括在请求地址中&a…...