一、知識點
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用于取地址
前++運算子與后++運算子
此處模仿了整數的++i與i++,所以前++運算子需要回傳一個參考,
個人理解:與左值和右值有關,如++i是左值,i++是右值,
_Self&
operator++() _GLIBCXX_NOEXCEPT //++item
{
_M_node = _M_node->_M_next;
return *this; //由于只有一個成員變數_M_node,因此能回傳*this
}
_Self
operator++(int) _GLIBCXX_NOEXCEPT //item++ 感覺跟左值右值有關
{
_Self __tmp = *this;
_M_node = _M_node->_M_next;
return __tmp;
}
_List_base
1. typedef
//rebind是一個模板類,它接受一個模板引數T和一個新的型別U,然后定義一個新的型別
//這個新的型別是將T中的模板引數全部替換為U后得到的結果
typedef typename _Alloc::template rebind<_List_node<_Tp> >::other
_Node_alloc_type;
typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
2. _List_impl
這段代碼定義了一個結構體
_List_impl,它是list類的一個內部實作,用于存盤list物件中的元素和節點資訊,該結構體中使用了兩個模板別名:
_Node_alloc_type和_Tp_alloc_type,它們分別表示節點和元素的分配器型別,這里使用了typename關鍵字來指示_Alloc::template rebind<_List_node<_Tp> >::other和_Alloc::template rebind<_Tp>::other是型別別名,而不是靜態成員變數或函式,接下來,
_List_impl結構體中定義了一個_M_node成員變數,它是一個_List_node_base型別的物件,用于存盤list物件中的頭節點和尾節點資訊,
_List_impl結構體還有三個建構式,分別用于構造一個空的_List_impl物件、使用指定的節點分配器構造_List_impl物件,以及使用右值參考的節點分配器構造_List_impl物件,需要注意的是,
_List_impl結構體中的_Node_alloc_type和_Tp_alloc_type型別別名都是使用_Alloc型別的template rebind成員模板生成的,這是因為list類需要支持自定義分配器,因此需要使用rebind將原始分配器重新系結到節點和元素型別上,
struct _List_impl
: public _Node_alloc_type
{
__detail::_List_node_base _M_node;
_List_impl()
: _Node_alloc_type(), _M_node()
{ }
_List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT //底層const
: _Node_alloc_type(__a), _M_node()
{ }
#if __cplusplus >= 201103L
_List_impl(_Node_alloc_type&& __a) _GLIBCXX_NOEXCEPT //右值參考
: _Node_alloc_type(std::move(__a)), _M_node() //轉為右值,移動語意
{ }
#endif
};
3. 建構式
這是
list類的一個基類_List_base,包含了list類的一些基本實作,這里的三個建構式都是_List_base類的建構式,第一個建構式
_List_base()是默認建構式,它使用默認的節點分配器構造了一個_List_impl物件_M_impl,并呼叫了_M_init()函式來初始化_List_base物件,第二個建構式
_List_base(const _Node_alloc_type& __a)則接受一個節點分配器__a,用于構造一個_List_impl物件_M_impl,并呼叫了_M_init()函式來初始化_List_base物件,第三個建構式
_List_base(_List_base&& __x)是移動建構式,它接受一個右值參考__x,用于構造一個_List_impl物件_M_impl,在構造程序中,它使用__x._M_get_Node_allocator()獲取__x物件的節點分配器,并將其作為引數傳遞給_M_impl的建構式,從而實作了節點分配器的移動,接著,它呼叫了_M_init()函式來初始化_List_base物件,并使用__detail::_List_node_base::swap函式交換了_M_impl._M_node和__x._M_impl._M_node兩個節點的資訊,實作了_List_base物件的移動構造,需要注意的是,該建構式只在 C++11 及以上版本中被定義,
_List_base()
: _M_impl()
{ _M_init(); }
_List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT
: _M_impl(__a)
{ _M_init(); }
#if __cplusplus >= 201103L
_List_base(_List_base&& __x) noexcept //右值參考
: _M_impl(std::move(__x._M_get_Node_allocator())) //移動建構式
{
_M_init();
__detail::_List_node_base::swap(_M_impl._M_node, __x._M_impl._M_node);
}
#endif
4. _M_init()
void
_M_init() _GLIBCXX_NOEXCEPT
{
//頭節點的prev與next指向自身
this->_M_impl._M_node._M_next = &this->_M_impl._M_node;
this->_M_impl._M_node._M_prev = &this->_M_impl._M_node;
}
list
1. typedef
// concept requirements
typedef typename _Alloc::value_type _Alloc_value_type;
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)
__glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
typedef _List_base<_Tp, _Alloc> _Base;
typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
typedef typename _Base::_Node_alloc_type _Node_alloc_type;
public:
typedef _Tp value_type;
typedef typename _Tp_alloc_type::pointer pointer;
typedef typename _Tp_alloc_type::const_pointer const_pointer;
typedef typename _Tp_alloc_type::reference reference;
typedef typename _Tp_alloc_type::const_reference const_reference;
typedef _List_iterator<_Tp> iterator;
typedef _List_const_iterator<_Tp> const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Alloc allocator_type;
protected:
// Note that pointers-to-_Node's can be ctor-converted to
// iterator types.
typedef _List_node<_Tp> _Node;
using _Base::_M_impl;
using _Base::_M_put_node;
using _Base::_M_get_node;
using _Base::_M_get_Tp_allocator;
using _Base::_M_get_Node_allocator;
2. 一些函式
_M_create_node
template<typename... _Args>
_Node*
_M_create_node(_Args&&... __args) //萬能參考
{
_Node* __p = this->_M_get_node(); //獲取新的節點指標
__try
{
_M_get_Node_allocator().construct(__p,
std::forward<_Args>(__args)...); //使用完美轉發構造節點中的資料
}
__catch(...)
{
_M_put_node(__p);
__throw_exception_again;
}
return __p; //回傳指標
}
assign
assign函式是list類的成員函式,用于將新的元素賦值給當前的list物件,該函式有多個多載版本,其中一個版本接受一個初始化串列作為引數,用于將初始化串列中的元素賦值給當前的list物件,具體地,該函式接受一個初始化串列
__l,它將__l中的元素替換當前list物件中的元素,為此,它呼叫另一個assign函式,該函式接受兩個迭代器引數,分別指向初始化串列的第一個元素和最后一個元素,assign函式用這些元素來替換當前list物件中的元素,需要注意的是,該函式只在 C++11 及以上版本中被定義,
#if __cplusplus >= 201103L
/**
* @brief Assigns an initializer_list to a %list.
* @param __l An initializer_list of value_type.
*
* Replace the contents of the %list with copies of the elements
* in the initializer_list @a __l. This is linear in __l.size().
*/
void
assign(initializer_list<value_type> __l)
{ this->assign(__l.begin(), __l.end()); }
#endif
3. 建構式
第一個建構式
list()是默認建構式,它創建一個空的list物件,使用默認的節點分配器,第二個建構式
list(const allocator_type& __a)接受一個節點分配器__a,用于創建一個空的list物件,第三個建構式
list(size_type __n)接受一個整數引數__n,用于創建一個包含__n個默認構造的元素的list物件,第四個建構式
list(size_type __n, const value_type& __value, const allocator_type& __a = allocator_type())接受一個整數引數__n和一個元素值__value,用于創建一個包含__n個值為__value的元素的list物件,第五個建構式
list(const list& __x)是拷貝建構式,用于創建一個與__x相同的list物件,第六個建構式
list(list&& __x) noexcept是移動建構式,用于創建一個與__x相同的list物件,并將__x中的元素移動到新的list物件中,第七個建構式
list(initializer_list<value_type> __l, const allocator_type& __a = allocator_type())接受一個初始化串列__l,用于創建一個包含__l中元素的list物件,第八個建構式
list(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type())接受兩個迭代器引數__first和__last,用于創建一個包含從__first到__last的所有元素的list物件,需要注意的是,該建構式只在 C++11 及以上版本中被定義,
list()
#if __cplusplus >= 201103L
noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value) //判斷是否支持默認建構式
#endif
: _Base() { }
/**
* @brief Creates a %list with no elements.
* @param __a An allocator object.
*/
explicit
list(const allocator_type& __a) _GLIBCXX_NOEXCEPT
: _Base(_Node_alloc_type(__a)) { }
#if __cplusplus >= 201103L
/**
* @brief Creates a %list with default constructed elements.
* @param __n The number of elements to initially create.
*
* This constructor fills the %list with @a __n default
* constructed elements.
*/
explicit
list(size_type __n)
: _Base()
{ _M_default_initialize(__n); }
/**
* @brief Creates a %list with copies of an exemplar element.
* @param __n The number of elements to initially create.
* @param __value An element to copy.
* @param __a An allocator object.
*
* This constructor fills the %list with @a __n copies of @a __value.
*/
list(size_type __n, const value_type& __value,
const allocator_type& __a = allocator_type())
: _Base(_Node_alloc_type(__a))
{ _M_fill_initialize(__n, __value); }
#else
/**
* @brief Creates a %list with copies of an exemplar element.
* @param __n The number of elements to initially create.
* @param __value An element to copy.
* @param __a An allocator object.
*
* This constructor fills the %list with @a __n copies of @a __value.
*/
explicit
list(size_type __n, const value_type& __value = https://www.cnblogs.com/grasscarp7/archive/2023/06/20/value_type(),
const allocator_type& __a = allocator_type())
: _Base(_Node_alloc_type(__a))
{ _M_fill_initialize(__n, __value); }
#endif
/**
* @brief %List copy constructor.
* @param __x A %list of identical element and allocator types.
*
* The newly-created %list uses a copy of the allocation object used
* by @a __x.
*/
list(const list& __x)
: _Base(__x._M_get_Node_allocator())
{ _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
#if __cplusplus >= 201103L
/**
* @brief %List move constructor.
* @param __x A %list of identical element and allocator types.
*
* The newly-created %list contains the exact contents of @a __x.
* The contents of @a __x are a valid, but unspecified %list.
*/
list(list&& __x) noexcept
: _Base(std::move(__x)) { }
/**
* @brief Builds a %list from an initializer_list
* @param __l An initializer_list of value_type.
* @param __a An allocator object.
*
* Create a %list consisting of copies of the elements in the
* initializer_list @a __l. This is linear in __l.size().
*/
list(initializer_list __l,
const allocator_type& __a = allocator_type())
: _Base(_Node_alloc_type(__a))
{ _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); }
#endif
/**
* @brief Builds a %list from a range.
* @param __first An input iterator.
* @param __last An input iterator.
* @param __a An allocator object.
*
* Create a %list consisting of copies of the elements from
* [@a __first,@a __last). This is linear in N (where N is
* distance(@a __first,@a __last)).
*/
#if __cplusplus >= 201103L
template>
list(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type())
: _Base(_Node_alloc_type(__a))
{ _M_initialize_dispatch(__first, __last, __false_type()); }
#else
4. 運算子多載
移動賦值運算子
list&
operator=(list&& __x) //移動賦值運算子
{
// NB: DR 1204.
// NB: DR 675.
this->clear();
this->swap(__x);
return *this;
}
初始化串列
這是
list類的賦值運算子多載,它允許使用初始化串列來為list物件賦值,該運算子多載接受一個初始化串列
__l,它將__l中的元素賦值給當前的list物件,具體地,它呼叫assign函式,該函式接受兩個迭代器引數,分別指向初始化串列的第一個元素和最后一個元素,assign函式用這些元素來替換當前list物件中的元素,該運算子多載回傳一個
list的參考,以支持鏈式賦值,
list&
operator=(initializer_list<value_type> __l)
{
this->assign(__l.begin(), __l.end());
return *this;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555673.html
標籤:其他
下一篇:返回列表
