一、知识点
1. std::bidirectional_iterator_tag
std::bidirectional_iterator_tag
是 C++ 标准库中定义的一个迭代器类型标签,用于标识支持双向遍历的迭代器类型。
在 C++ 中,迭代器是一种泛型指针,用于遍历容器中的元素。迭代器类型标签用于标识迭代器的特性,从而在算法中选择合适的迭代器类型。
std::bidirectional_iterator_tag
是迭代器类型标签中的一种,用于标识支持双向遍历的迭代器类型。双向迭代器可以向前和向后遍历容器中的元素,支持 ++
和 --
运算符。
标准库中的许多算法都要求迭代器支持特定的操作,例如 std::reverse
要求迭代器支持双向遍历,因此可以使用 std::bidirectional_iterator_tag
标签来限定迭代器的类型,从而保证算法的正确性。
//迭代器类型标签,用于标识支持双向遍历的迭代器类型,支持++和--运算符
typedef std::bidirectional_iterator_tag iterator_category;
2. ptrdiff_t
ptrdiff_t
是 C++ 标准库中定义的一个整型类型,用于表示指针之间的差值(即两个指针在内存中的地址差距)。在 C++ 中,指针的加减运算结果是一个 ptrdiff_t
类型的值。
ptrdiff_t
的实现是平台相关的,通常是一个带符号的整数类型。在 32 位平台上,ptrdiff_t
通常是一个 4 字节的整型,而在 64 位平台上,ptrdiff_t
通常是一个 8 字节的整型。
使用 ptrdiff_t
类型可以保证指针操作的安全性,因为指针之间的差值可能超出普通整型的表示范围。此外,使用 ptrdiff_t
类型还可以提高代码的可移植性,因为不同平台上指针的大小可能不同。
//带符号整型,表示指针之间的差值(即两个指针在内存中的地址差距)
typedef ptrdiff_t difference_type;
3. #if __cplusplus >= 201103L
#if __cplusplus >= 201103L
这行代码是C++中的条件编译指令,意思是如果当前编译器支持C++11标准或更高版本,则编译下面的代码。其中,__cplusplus
是一个C++预定义宏,表示当前编译器所支持的C++标准版本,201103L
表示C++11标准的版本号。因此,这行代码的作用是在编译时检查当前编译器是否支持C++11标准或更高版本,如果支持,则编译下面的代码,否则忽略。
4. explicit
explicit
是 C++ 中的一个关键字,用于修饰类的构造函数,表示该构造函数是显式的,不能进行隐式转换。
在 C++ 中,如果一个类的构造函数只有一个参数,那么这个构造函数可以被用于隐式转换。例如,如果有一个类 A
和一个构造函数 A(int)
,那么可以使用 A a = 1;
的方式创建一个 A
类型的对象,这里的 1
会被自动转换为 A
类型。
使用 explicit
关键字可以禁止这种隐式转换,从而避免一些潜在的问题。例如,如果一个类 B
有一个构造函数 B(int)
,但是我们希望这个构造函数只能显式调用,那么可以将其声明为 explicit
,这样就不能再使用 B b = 1;
的方式创建一个 B
类型的对象,而必须显式地调用 B b(1);
。
另外,explicit
关键字还可以用于修饰转换函数,表示该函数也是显式的,不能进行隐式转换。
5. stl_list.h结构
6. 迭代器相关
- 运算符重载
重载++
(分为++item与item++)
重载*
、&
7. 迭代器 traits
-
模板偏特化(感觉类似java泛型重载)
-
完整的iterator_traits
二、源码
_List_node_base
主要提供了prev和next指针,以及一些方法。
struct _List_node_base
{
_List_node_base* _M_next;
_List_node_base* _M_prev;
...
};
_List_node
继承自_List_node_base,主要提供了一个存放数据的 _M_data
/// An actual node in the %list.
template<typename _Tp>
struct _List_node : public __detail::_List_node_base
{
///< User's data.
_Tp _M_data;
//检查编译器是否支持c++11及以上版本
#if __cplusplus >= 201103L
template<typename... _Args>
_List_node(_Args&&... __args) //万能引用
: __detail::_List_node_base(), _M_data(std::forward<_Args>(__args)...) //完美转发
{ }
#endif
};
_List_iterator
迭代器
1. 必须定义的五个typedef
//下面这五个typedef是每个iterator必须有的
//带符号整型,表示指针之间的差值(即两个指针在内存中的地址差距)
typedef ptrdiff_t difference_type;
//迭代器类型标签,用于标识支持双向遍历的迭代器类型,支持++和--运算符
typedef std::bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Tp* pointer;
typedef _Tp& reference;
2. 两个构造器
_List_iterator() _GLIBCXX_NOEXCEPT
: _M_node() { }
explicit //修饰类的构造函数,表示该构造函数是显式的,不能进行隐式转换
_List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPT
: _M_node(__x) { } //_M_node:_List_node_base
3. 运算符重载
个人理解,此处之所以能够向下造型,应该是传入参数的时候已经做过一次向上造型
// Must downcast from _List_node_base to _List_node to get to _M_data.
reference
operator*() const _GLIBCXX_NOEXCEPT
{ return static_cast<_Node*>(_M_node)->_M_data; } //_M_node:_List_node_base, _Node:_List_node<_Tp>
pointer
operator->() const _GLIBCXX_NOEXCEPT //2.9版本中是return &(operator*())
{ return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); } //__addressof用于取地址