当前位置: 首页 > wzjs >正文

网站不备案违法吗免费换友情链接

网站不备案违法吗,免费换友情链接,网站设计的研究方法有哪些,国外设计素材网一.vector的基本使用 1.1vector的基本概念 在 C 里,std::vector是标准模板库(STL)提供的一个动态数组容器。它能存储同一类型的多个元素,而且可以在运行时动态改变大小。 其实vector就是一个顺序表,而顺序表我们之前…

一.vector的基本使用

1.1vector的基本概念

在 C++ 里,std::vector是标准模板库(STL)提供的一个动态数组容器。它能存储同一类型的多个元素,而且可以在运行时动态改变大小。

其实vector就是一个顺序表,而顺序表我们之前都学习过,所以vector和string底层都为数组,所以两者在库中的一些接口等都非常相似:

可以看出vector的接口很多都是我在string类中讲过的,并且因为两者底层都为数组,所以在使用上也是基本一样的。

1.2vector的基本使用

因为和string高度相似,所以我就演示一下vector的基本用法,主要是将下面的实现vector,来帮助我们更好地理解vector。

尾插和遍历数组都和string是一样的,唯一的区别是我们在创建vector对象时要加上<>,里面标明数组中的数据是什么类型。

迭代器和范围for来遍历数组也是和string一样的方式。

二.vector的实现

2.1vector框架的实现

和之前的string一样,首先把vector的框架写出来。

和之前string不一样的是,这里vector我们要用到模板,因为底层vector就是用模板那来实现的。

另外成员变量也能也有人不理解,这里这样定义成员变量的名字和成员变量的类型是因为vector底层源代码是这样定义的,源代码大家有机会可以看看,我们既然实现vector,就尽量跟着底层走。

我们知道vector本质是一个顺序表,所以_start代表的就是首元素地址,_finsh代表的就是最后一个元素的下一个位置,_end_of_storage代表的就是容量。

因为它们都是指针,所以构造和析构实现时都把它们置为nullptr,另外把begin和end这两个迭代器实现了,后面也会使用。

注意:这次vector中各种接口的声明和实现都要在类内实现,因为我们使用了模板,模板如果分开声明和实现会出现链接错误。

2.2cpapcity的实现

这里直接用_end_of_storage - _start就可以直接得到此时数组容量的大小,指针相减得到就是两个之间的大小。

2.3size的实现

同样的方式,用_finsh - _start就可以得到数组中数据的数量。

2.4reserve的实现

在实现reserve中,如果此时_start为空,就可以直接让_start接收tmp的位置。

这里面最大的问题就是计算_finsh的位置,如果不提前计算此时的size,那么后面扩容后,_start已经转移到新的地址,而此时我们调用size来计算_finsh时,就会出问题。

因为此时_start在新的空间,而_finsh在旧的空间,如何计算size?

直接相减肯定会出问题,所以要提前计算size的大小,就是为了避免这种问题。

剩下的就是通过_start来找到_finsh和_end_of_storage的位置即可。

2.5push_back的实现

逻辑和之前实现string中的push_back一样,在尾插前检查此时数组是否满了,满了就扩容,最后在_finsh处加上目标值,并令_finsh++即可。

2.6pop_back的实现

这个实现起来就很简单,不需要将最后一个值置为0,因为如果走后一个值本来就是0呢?

所以_finsh--即可。

2.7[]符号的实现

实现起来也比较容易,直接返回相应下标的值即可。

2.8insert的实现

insert大体逻辑和之前string中之一样的,不一样的是在string中我们用下标来遍历数组,但是会出现头插时类型提升的问题,这次我们使用指针来实现,可以解决之前的问题。

但用指针又出现了新的问题,就是图片中所说的迭代器失效的问题,解决问题的关键就是pos,上面的代码是解决问题后的代码。

我们接下来看看如果不做处理,迭代器失效会出什么问题:

注意:要检查本身insert中代码实现是没问题的。

此时就出现问题了,insert本身的代码是没问题的,我们再看另一个现象:

此时又没问题了,我们通过刨析代码发现,出现这两种情况是因为第一个扩容了,而第二个扩容了,第二个例子没问题说明reserve本身是没问题的,那么就是因为扩容才导致了这种问题。

其实这个问题和上面reserve遇到的问题很相似:

用图来解释就是我们扩容后,_start已经来到了新的空间,而pos依旧指向旧空间,那么在通过it和pos位置遍历数组是不是就会出问题?

这就是迭代器失效,在这里本质上就是野指针的问题。

而为什么第二个例子没有问题的呢?

因为第二个例子在尾插前就已经扩容过了,此时空间没有满,用的还是原来的空间,所以不会出问题,所以为了解决第一个例子出现的迭代器失效的问题,我们在扩容前就记录下pos和_start之间的距离,扩容后更新pos的位置,这样就能解决问题。

我们再来看一个问题:那尾插后我要访问pos位置处的值呢?


已经解决了扩容后导致的问题,为什么又不能访问pos的值了呢?明明已经更新了pos的位置。

因为我们实现的是传值调用,如果用引用就可以解决这个问题,但是此时又会出现新的问题:

我们在这种使用时就会出问题,因为此时的pos是临时对象,而临时对象具有常性,也就是之前讲的权限扩大的问题,可能又会与人说加个const就行了,那又会出现新的问题,这里我就不过多赘述了,而底层用的也是传值调用,所以就按这个来。

所以说呢insert之后就默认pos已经失效了,不能再使用pos了,因为并不清楚底层什么时候会扩容。

2.9构造函数的其他实现方式

这两种方式都是对数组进行初始化,第一种方式是初始化为n个一样的值,第二种方式是直接初始化为任意个一样或不一样的值。

第一种方式中的参数利用了匿名对象,因为要给缺省值,但是不能直接给0,因为数组中不一定就是整型,所以利用匿名对象就可以解决这个问题。

第二种方式的参数有的人会看不懂,这种方式其实c++11中引入的一种方式,它是std标准库中的,它里面自带begin,end和size。

两种构造函数的基本用法就如上图所示。

2.10erase的实现

这是正常情况下我们要实现的erase函数,但是这种方式会出问题:

这里我们先用系统给的vector来实现这段代码,发现出现了错误,但是我们检查这段代码的逻辑是没有问题的,会出现这个错误的原因就是和上面一样,都是迭代器失效的问题。

因为在vs编译器下,如果调用了erase函数,会默认当前的迭代器已经失效,然后会强制检查迭代器,所以我们对vv++就会出问题。

而在其它编译器下不一定会有这种问题,就比如g++编译器下,就不会强制检查,所以相同的代码下就不会报错。

所以我们要怎样解决这种问题呢?

其实只需要更新迭代器的位置即可,使它是有效的,具体过程如下:

将erase函数返回的位置赋值给vv即可,其实vv本身的位置没有改变,只不过将它原本的值重新赋值给自己而已,使其重新变为有效的迭代器,所以我们上面写的erase函数就不太合适,应该写成如下这样:


其实去看vector底层实现的erase接口,也是这样实现的,是有返回值的,不是我们之前实现的void。

2.11resize的实现

vector中resize的实现比较string就会更容易些,就分为两种情况,大于capacity和小于等于capacity,大于capacity是扩容+插入数据即可,小于等于时,更新_finsh的位置即可。

即使感觉如果n>size && n<capacity这个范围怎么办,其实缺省值就把这个问题解决了,超出的部分都初始化为0。

2.12=符号的实现

=符号的实现需要用到swap函数,这样实现起来其更为简单。

swap:我们之前的传统逻辑是再创建一块空间,把其中一个数据先拷贝到临时空间,再进行交换。而现在使用的现代写法直接交换两个指针,不需要再创建新的空间。

可能有人会疑惑为什么还要交换_finsh和_end_of_storage,如果不交换这两者的话,那么交换后的_start中的_finsh和_end_of_storage是不对应的,这么做就会使两者的意义就没有了,所以两者也要交换。

注意:要使用的是std标准库中的swap函数,std库中的swap函数是一个模板,string和vector中的swap接口都是基于std标准库中的swap函数来实现的。

完成swap函数再实现=符号就简单许多,直接交换即可,最后返回*this。

注意:这里不能使用引用,因为我们实现的是=符号,不能改变等号右边的值,所以要使用传值调用。

最后再来看一种现象:

我们不再使用int类型,使用string类型,此时我们在vector插入几段字符串没有问题把,我们再看:

此时就会出问题了,但问题出在哪儿了呢?

很明显,问题出在扩容这步操作了,但是扩容我们之前都已经试验过了,没有问题,我们来调试看看:

我们发现在经过delete这段代码后,就出现这种现象了,那说明delete这部操作有问题,但是_start指向的就是一个数组,这样delete没有问题啊。

是的,怎么看这段代码都没有问题,那么是哪里出的问题呢?

这里我直接就说答案了,是memcpy出的问题导致的这种现象,我们通过画图来演绎出memcpy的过程:

把图画出来后相信大家一眼就看出问题出在哪儿了,这就是使用memcpy的弊端,当vector中是内置类型时,这么写是没有问题的,但是对于自定义类型这么些就不行了。

所以要怎样解决这种问题呢?,很简单:

直接利用循环一个个复制过去即可,有人会疑惑为什么这样就可以解决了呢?
拿string举例,当赋值的时候,就会调取string中的拷贝构造函数,而string底层中的拷贝构造函数是深拷贝,所以就解决了这种问题,内置类型就更可以实现了。

以上就是vector的内容。

http://www.dtcms.com/wzjs/493439.html

相关文章:

  • 别人做的网站不能用seo的基础是什么
  • 网站的图形拖拽验证码怎么做的营销计划怎么写
  • 做橡胶的网站企业推广软件
  • 有没有免费做网站的免费seo公司
  • wordpress识别手机跳转网站汕头seo优化
  • 政务网站建设建议现在推广用什么平台
  • 杭州定制网站江西seo推广软件
  • 天津微信网站模板自助建站
  • 网站icon图标怎么设置18款免费软件app下载
  • 计算机入门基础知识seo整站优化方案案例
  • 网站有源代码如何做seo市场调研报告总结
  • 建设一个网站需要什么技术哈尔滨百度关键词优化
  • 网站建设需要的设备和软件自助建站免费搭建个人网站
  • 怎么申请免费国内免费网站浏览器大全网站
  • 网站title keyword description比较好的品牌策划公司有哪些
  • 山西网络营销企业seo推广外包
  • 网站建设 人员 年终总结百度推广软件
  • 网站制作西安拉新推广平台
  • 网站建设目标及需求优化大师官方免费
  • 视频制作和剪辑软件seo学校
  • 站酷官网入口sem数据分析
  • erp软件定制开发seo优化工作内容
  • 一个专业做设计的网站2020国内搜索引擎排行榜
  • 嘉兴免费网站制作qq代刷网站推广免费
  • 南昌网站建设规划方案可以免费发广告的网站有哪些
  • 广西壮族自治区卫生健康委员会网站中国seo第一人
  • 北京网站推广外包活动推广方式
  • 技术支持 东莞网站建设东莞天助专业做app软件开发公司
  • 做营销网站多少钱小红书怎么做关键词排名优化
  • 建设外国商城网站关键词优化百家号