C++——list迭代器的模拟实现(入门)

前言:

目前学习阶段遇到最难的一部分,可能与我一开始思考方向不对有很大的关系。因此,从最开始就要纠正自己的错误。

认识迭代器:

👉:容器迭代器设计思路体现了C++三大特性中的封装,屏蔽底层实现细节和结构差异,从而提供统一的访问方式解引用++操作无法正常访问数据时,这个时候就要改变底层的设计,使其能够进行解引用和++操作

认识封装:

👉:我们现实生活中各种各样的银行卡:工商、建商、农行......各个银行卡底层的支付方式都不一样,因此线上支付的逻辑就是将不同银行的支付方式进行一个封装,我们不用管他底层是怎么样实现的,但是访问方式都是统一的,即扫码付款。

一、list迭代器与string/vector之间的区别

这里说的区别主要从模拟实现的方式去考虑,而非库函数中自带的list、string以及vector。

先前学习string/vector时,迭代器的底层完全可以说成是指针。我们可以很轻松的写出如下代码:

int main()
{
	jc::vector<int> lt1;        //此vector 在命名空间jc中定义
	vector.push_back(1);
	vector.push_back(1);
	vector.push_back(1);
	vector.push_back(1);

	jc::vector<int>::iterator it1 = lt1.begin();
	while (it1 != lt1.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
}

因为底层是指针:

👉:可以直接进行解引用得到数据

👉:可以直接通过++去访问到下一个数据的地址

★★★

但list底层模拟实现迭代器的方式与前两者完全不同!

因为当我们去创建一个链表的时候,解引用得到的是一个节点,而非我们所想要的数据。

而当我们对数据进行++处理时,因为链表中节点地址是不连续的,因此++操作会使得我们丢失原来的数据。

为了能继续使用解引用操作++操作,我们需要通过运算符重载的方式去实现迭代器,因此需要在命名空间里定义新的对象,来封装节点指针,重载运算符,去模拟指针的行为

二、代码分析

通过下述代码来分析这一过程。

👉大致过程(从测试开始)

1:通过下列代码,创建了一个链表:lt1 。随后插入四个数据。

void empty_init()
	{
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
	}

	list()
	{
		empty_init();
	}

2:此处的迭代器不再是指针,而是struct类类型对象 it1,类型为:list_iterator<T>

       

bit::list<int>::iterator it1 = lt1.begin();

问:lt1.begin();实现了什么?

答:如图所示,匿名对象会调用相应自定义类的构造函数,此处临时构造一个 list_iterator<T> 类型的临时对象tmp,并返回给 it1,同时将_hear->next的指针(链表的头)传递给了成员变量_node,当此行结束时,匿名对象tmp结束生命周期

而这个_node是整个代码中,最核心的部分,因为他是链表的头节点,包含了所有信息,通过这个节点,我们可以访问所有的数据,“魔法”由此开始

3:循环过程

根据先前所学的运算符重载的知识,*it1会调用函数①,先前_node已经保存了链表的头节点,因此通过_node->_data便可直接访问数据。

而++it1则会调用函数②,通过_node->_next即可访问链表的下一个节点。

注:

1:时刻牢记此处 it1 不再是指针,而是类类型对象

2:&it1 为隐含的this指针 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值