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

c++ vector模拟实现细节

1.reserve

预留空间,只有在想要的空间大于现有空间时才会扩容。但还要注意——start不能为空。

这里不能使用memcpy,因为底层其实是浅拷贝。所以应该自己进行深拷贝。tmp是一个数组,里面可能存放的是自定义类型,自定义类型的话,在其类中会有重载的赋值函数,所以直接使用如上佛如循环的方式即可。

但是注意,operator[]也要写。

还有一个,T tmp=new这里,应该是T*,指针类型!!!!

仔细看这个函数,这里有错,更新finish是有错。因为size是用finish减去start,但是走到这一步的时候,start已经更新了,所以计算size就会出错。所以最稳妥的办法就是提前将size记录下来。如下:

2.push_back

3.构造函数

这里一定要提供无参的构造函数,因为不可能每次创建容器的时候都能及时提供内容。

也想上面写的,防止出错,将三个指针在声明时提供nullptr缺省值,如下:

第二个构造函数,直接复用pushback,但注意这个构造函数的第二个参数,它的缺省值是一个匿名对象,匿名对象具有常性,所以要用const接收

4.insert——迭代器失效问题

end是iterator,我们是将T*定义成了它,所以end存放的是元素的地址。所以给对应位置赋值就是解引用。

有了insert之后,pushback就可以直接复用他了,如下/;

但是当插入时却报错了

如上调试可以看到,本来尾插传入的是_finish的值,但是走到这里,pos没跟随着_finish变,还是原来的值(原来容器为空,所以finish当时是null)。

为什么呢?因为在reserve中进行了扩容,会把新的地址给到finish,但是pos没随着修改!!这里就是pos失效了,也就是迭代器失效了!!!那怎么办??使用引用传参给pos吗?好像也可以

但其实不行/!!因为可能会这样传参:insert(v.begin());这样的话v.begin()要返回一个迭代器对象,传值返回过程中产生的临时对象具有常性,不可以。那该怎么办?只能是在reserve之后手动修改pos的指向。如下:

5.erase——迭代器失效

当测试一段去掉偶数的代码时,出错了

为什么呢?调试一下,会发先,删除了一个元素后,就会有++it和--finish的操作。这里会有两种情况:假设,有两个连续的偶数,那么删除了第一个之后,it++正好就跳过了第二个整数;而假设有一个偶数在末尾,那么删除之后,就会有++it和--finish,操作后,正好finish在it前面,还是满足it不等于finish,然后又进行while判断对非法it解引用,程序就会崩溃。那么怎么解决呢?在苦衷是通过返回被删除元素的地址来解决,如下:

将erase函数加上返回值,并在erase后让it接收,如下:

上面的问题也是一个迭代器失效的问题

6.reserve深度解析

这里详细说一下为什么不能使用memcpy。

如果是如下写法:

向vector中放置string类型的数据,当涉及到扩容时,就可以观察出现象:

当只插入四个字符串时,正常。但当插入五个涉及到扩容时就出错了

这是为什么呢?因为,memcpy是浅拷贝,memcpy(tmp,_start,size)这样只是将*start的值都给到了*tmp,但是,*tmp是一个string对象,里面有个字符指针,这样的拷贝会让*tmp中的指针和start指向同一块空间,然后又调用了delete[],而delete不仅仅是释放start指向的空间,还会对空间里面的对象进行析构,也就是会调用string的析构函数,这样一析构就导致start中的字符指针指向的空间被脂肪,那么tmp再去访问就不是原来的内容了

所以不能使用memcpy,只能使用string自己的赋值重载,也就是:

7.拷贝构造

有两个点,第一个,for里面的内容可以改为尾插。第二个,v是常量,无法调用非const的成员函数,所以要写个const的capacity函数。

如下:

8.迭代器区间构造函数

但是可能会用其他类的迭代器对容器进行构造,比如用char类型的迭代器对int容器进行构造。所以这个构造函数的参数可以使用模板,如下:

有了这个构造函数后,还会出现新的问题,比如现在是想给容器中插入10个0,如下:

为什么会调用这个函数呢??

对于这两个构造函数,v(10,0)参数是两个整型,相对于上面的构造函数,更匹配与模板函数,所以调用了下面的函数。

那怎么解决??专门提供一个int的构造函数,如下:


http://www.mrgr.cn/news/22179.html

相关文章:

  • C++入门基础篇
  • 2024年必看的4款录屏新星,谁才是你的菜?
  • 查ASCII码带来的MAN
  • Java——堆
  • C++ 定时器
  • C++——类与对象(二)
  • docker ps -a及docker exec -it ubuntu-01 /bin/bash
  • Qt常用控件——QPushButton
  • GEE Python案例——通过机器学习算法检测 Portonovo 和 Trave 悬崖之间的崖顶侵蚀驱动因素(意大利安科纳)
  • Oracle full back时为什么不备份online log
  • GD32F103单片机-概述和工程建立
  • Bev pool 加速(1): torch.autograd.Function的使用
  • 经典栈和队列OJ题
  • API 架构(RPC风格、RESTful风格)
  • 用Pytho解决分类问题_DBSCAN聚类算法模板
  • C++函数提高
  • 在Python中读取Excel文件
  • PAT甲级-1085 Perfect Sequence
  • Linux下的PWM驱动
  • C++万字解析类和对象(上)