帮人做项目的网站,几个月网站没有排名,主题营销活动创意,网站主题和建设一、结点的定义 有三个成员#xff0c;2个指向前面和后面的指针#xff0c;一个表示结点存储T类型的值。
对于_prev和_next#xff0c;类型是 list_nodeT*#xff0c;不是list_node*#xff0c;加上类型参数T之后#xff0c;才是模板类的类型。
构造函数中2个指向前面和后面的指针一个表示结点存储T类型的值。
对于_prev和_next类型是 list_nodeT*不是list_node*加上类型参数T之后才是模板类的类型。
构造函数中先把指针置空然后val可以给一个默认构造的缺省值。
二、普通正向迭代器 先将list_nodeT typedef为Node便于后续使用更方便。
一个成员变量为 Node* _node表示迭代器当前指向的那个结点。
构造函数中用传入的node初始化_node指针为内置类型浅拷贝即可。
1、operator*()
对迭代器解引用返回的是那个T类型的值val的引用。无论T是内置类型还是自定义类型
2、operator-()
返回的是val的地址。
当val是结构体/自定义类型val内部可能还有多个要访问的值。
可以直接通过返回的地址/指针用-找到其中要访问的值。
3、/--/ 是让迭代器指向下一个结点即让其成员_node变为_node-next。--同理。
前置和--返回下一个/前一个迭代器位置即改变后的*this的引用。
后置和--要先用tmp保存改变前的位置最后传值返回tmp的拷贝。
三、const迭代器 首先对于所有迭代器都是可以--修改的。
对于T*这种由原生指针指针解引用就可以访问且内存连续直接找到下一个结点构成的迭代器直接在 T*前加const使得其无法解引用修改存储的值即可构成const_iterator。
但由于list中内存不连续且有时解引用得到的val为结构体不方便。
我们需要对--*-等进行运算符重载因此就要定义一个__list_iterator的结构。 直接在迭代器类型前加const是错误的这样使得const_iterator的类型变成了一个const对象不能进行--等操作。const_iterator的const修饰的是对访问那个结点的值是否具有修改的权限 如上图返回的引用的值是否加const 修饰。
对于函数重载我们只能通过参数类型/个数/顺序来区分这里是仅通过返回值无法区分两个operator*()。
一种解决方法是重新定义一个const_iterator结构仅在operator*()这里与iterator不同但代码冗余度太大重复部分太多。
还有一种方法是引入新的模板参数 Ref作为引用的返回值 iterator和const_iterator靠Ref和Ptr两个模板参数区分。看传入的T和T*是否加const修饰。
实际上两种迭代器仍然是两种结构只不过我们用模板传入模板参数让编译器生成了两个模板类两个模板类通过对访问数据是否有修改来区分。 先在ls内插入数据然后用const引用接收在Print函数内*cit无法被修改
四、insert/erase 五、拷贝构造/operator 空初始化为创建头节点用的地方比较多可以单独拿出来。
拷贝构造直接循环尾插即可。
赋值重载使用现代写法交换得到_head指向拷贝得到的list。
注意由于ls被const修饰beign()返回的是const_iterator需要用const迭代器接收
ls要完成交换不能加const std::swap需要两个参数
六、clear/析构 循环删除时迭代器会失效接收返回值更新一下。 size()函数每次统计结点个数为ON
也可以增加一个成员变量每次插入时删除时--
目录
一、结点的定义
二、普通正向迭代器
1、operator*()
2、operator-()
3、/--/
三、const迭代器
四、insert/erase
五、拷贝构造/operator
六、clear/析构