list本身就是一个node ,一个指针, 一个节点
这里是gnuC 2.9版本
除了绿色的数据本身,还要附带两个指针
这里的指针是void_pointer
类型 , 即 void*
可以运作,但是不够好,在学校老师会给你扣一分。
所以在程序设计里还需要转型。为何不用 __list_node *
.
后面知道,在gnu 4.9版本确实有改善。
尾节点
所有容器表现头尾时候,是前闭后开区间
4.9版本的实现中去掉了尾节点中的数据域。
迭代器:
这里的迭代器 不能是指针,因为list是不连续的内存空间。
所有容器的迭代器都是一个class,通过typedef,访问内部指针:
为什么要传递三个参数,只要传一个T 就好了。
新版本4.9 就只传了一个,下图是gnuC 2.9:
typedef也是有作用域的:
#include <iostream>
using namespace std;
int main(){
{
typedef int qin;
qin a=6;
cout<<a<<endl;
}
qin b;
return 0;
}
这里声明b的部分就报错,因为qin只在前一个作用域内{}有效。
对于++的重载
为何区分前置和后置, operator++(int) 代表 i++ 即, 后++
operaor++() 代表++i 即 前++
记忆的话,int 在后表示 后++ 即++在后
具体实现:
这里的self就是迭代器类 类型(typedef)
注意:后置加加,上图的上面的++操作符,并没有 记录原值的代码并没有调用重载的 * , ,调用 拷贝构造函数。
因为*this已被解释为 这个函数 的参数。还记得以前说过的,编译器实际上是将指向类本身的指针this当做参数传入成员函数 (非静态成员函数),好吧,这句话不能解释清楚。。
???
重新理解一下,this是指向类本身的指针。解引用是类本身。
而这个list的迭代器 类,本身模仿指针的行为,要重载 * 符,获得data,而不是类本身。
这里重载++时候,对this解引用到底是 获得data ?还是类本身 。 当然这里是 类本身。
为什么呢?
搞混了吧?再理一下:this是指针,类是迭代器, 这里的this 是迭代器 这个 类的指针。解引用获得的是这个类本身。而对 这个类本身重载操作符,是对 迭代器类 使用 解引用符。
总算理清楚了。。
另外注意 前++ 和 后++ 的返回类型 ,一个是 不带引用,另一个带引用。
为什么要这样呢?
https://zh.cppreference.com/w/cpp/language/operators
看一下在整数中的表现:
可以连续使用 前++
但是不能连续使用 后++
所以在后++ 重载时 不返回引用
前++ 重载 返回引用 (连续使用操作符)
返回引用 会唤起 * 重载? 不会唤起什么
*操作符 重载
前面提到的版本改进
- 只传递一个T,不再传递用 T&和T*。
- 指针类型 ,使用 指向 容器内 元素类型的指针,不再是空指针。
然而 4.9版的list 写的太过复杂,跳来跳去。不如2.9版本的简单明了。
所以之前的sizeof(list<T>)
从4变成 8了。(32位系统,8 bit 一个字节,所以指针 占用32/8= 4个字节)
2.9版用一个指针指向尾节点,所以是 4
而4.9版变了,一点小差别 。直接包含的这两个指针。所以是 8个字节。
每个容器的迭代器 都要有的 5个typedef
为什么需要这个东西呢?扯到一个大题目,叫traits
下一部分,关于迭代器的设计原则和 Iterater Traits 的作用和设计。