| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> vector的简单模拟 -> 正文阅读 |
|
[数据结构与算法]vector的简单模拟 |
目录 构造与析构模拟实现时,依然使用vector作为容器的名字,为了防止与std命名空间中的vector冲突,使用自定义的命名空间,将模拟实现的类放入即可。vecotr容器中可以存储多种类型的值,所以需要使用模板的方式。类的实现方法也有多种,以下实现采用三指针的方式,比如容器中的有效元素是两个,容量为6,那么其内部结构下图: 给出三种构造函数,无参构造函数、n个元素的构造函数、给定迭代器(类似于指针,以下代码默认为指针)区间的构造函数。代码如下:
构造函数比较简单,就是开辟新空间,将给定的元素放入申请的这段空间中就可以。需要注意的是:给定迭代器区间构造的过程中,不能使用给定的两个迭代器直接做减法,因为这两个迭代器可能是链表的,也就是说底层空间不连续。 以下给出的代码都放在命名空间gss中的vector类中。 简单方法的模拟如下是迭代器、计算元素个数、计算容量、以及[]重载的模拟:
拷贝构造与赋值运算符重载浅拷贝问题如下代码,如果在拷贝构造的时候,仅仅只是将arr中变量的值拷贝给arr1,那么在这两个对象中的_start指针将会指向同一块空间,在最后对象声明周期结束后调用析构函数时,_start指向的空间将会被释放两次,运行直接报错。浅拷贝后 深拷贝vector容器中的拷贝构造与赋值运算符重载都是深拷贝,也就是说要把原来对象中指针_start指向的空间中的内容拷贝一份,然后让新对象中_start指针以及其他指针指向新的空间,代码如下:
赋值运算符重载也可以使用类似于以上的方式给出,完成深拷贝,但是这样代码显得有点重复,接下来使用一种比较简洁的思路给出代码:
看到这段代码,很多同学心里会有疑惑,这么简单一段代码就完成了赋值运算符重载? 我们来分析一下以上代码,调用赋值运算符重载的时候,s是一个形参,也就是说传递参数的时候s是调用拷贝构造构造出来的临时对象,那么只需要让s中的指针与被赋值对象中的指针交换即可,用一副简图来理解一下: 而且交换完成以后,临时对象出了函数作用域生命周期会结束,在生命周期结束后,编译器会自动调用析构函数来释放临时对象的资源,所以也不用担心内存泄漏。 ?扩容reserve()
reserve()函数是将增加对象的容量,并不改变有效元素的个数,如果要扩容的容量小于原来对象的容量,则不做处理。代码如下:
这段代码要注意两个点: 第一点就是首先需要调用size(),将原空间有效元素个数保存起来,因为_finish最后的指向需要在_start的位置上加上原空间有效元素的个数。 第二点:在拷贝旧空间元素时,不能使用memcpy()函数进行拷贝。如果vector容器中保存的是基本类型的变量,那么使用memcpy()没有问题。如果保存的是string类型(底层也使用指针)的变量,此时使memcpy()进行拷贝只是将gss::vector<string>容器中_start所指向的内容拷贝了一份,而这些被拷贝的内容只是string类对象中的指针以及其它值,真正的字符串并没有被拷贝。下图表示对gss::vector<string>类型对象扩容时,在reserve函数中使用memcpy()的结果: 很明显,扩容后容器中的string类型对象中的指针还是指向了原来的空间,但是原来的空间在拷贝结束后就被释放掉了。所以说memcpy()在这里是不能使用的。 那为什么循环的方式就可以呢? 因为temp[i] = _start[i];这句代码对于string类型的对象可以调用他们的赋值运算符重载,完成深拷贝。 resize()resize()的作用是改变对象有效元素的个数,在C++库中对resize的定义是这样的: ?如果n小于有效元素的个数,那么直接将有效元素个数改为n个。如果n大于有效元素个数,但是小于容量,那么有效元素个数改为n,n个元素中默认值的部分直接补成val。如果n大于容量,那么先扩容,在将有效元素个数改为n,n个元素中默认值的部分直接补成val。 代码实现如下:
插入与删除push_back()尾插是比较简单的,但是要注意的是需要判断容量是否够用,以及刚开始容量为0时,第一次扩容问题。代码如下:
insert()insert是在任意位置插入n个元素,第一个参数是迭代器类型的。其中一种的模拟实现如下:
?注意:扩容后position就失效了,需要及时更新,然后在插入元素。 erase()erase是删除对象中的元素,来实现其中的一种。
注意:该函数的返回值是要删除的元素下一个位置元素对应的迭代器。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 7:44:10- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |