STL 的 slist 分析(三)

#-slist #-STL

函数 begin 返回指向 slist 第一个元素的迭代器,当前类中继承了基类的成员 _M_head。_M_head->next 是 _Slist_node_base 类型的指针,它指向的是 slist 中的第一个节点。因为 slist 中的节点是 _Node (_Slist_node<_Tp>) 类型的,所以可以用强制转换将其转换为 _Node 类型的指针。iterator (_Slist_iterator<_Tp, _Tp&, _Tp*>) 中有一个形参 _Node 类型的构造函数。

  iterator begin() { return iterator((_Node*)this->_M_head._M_next); }

函数 end 返回 slist 最后一个节点的后向指针 (_M_next) 指向的内容,最后一个节点的后向指针为空指针,指向的内容为空。

  iterator end() { return iterator(0); }

函数 before_begin 返回指向 slist 中的第一个节点之前的那个节点的迭代器,也就 _M_head 。但 _M_head 是一个 _Slist_node_base 类型的实例,没有存储数据,因此是不能调用 operator* 进行解引用的。函数中首先获取到指向 _M_head 的指针,并将其强制转化为 _Node 类型的指针,用得到的 _Node 类型的指针初始化迭代器。最后将生成的迭代器作为返回值返回。

  iterator before_begin() { return iterator((_Node*) &this->_M_head); }

函数 size() 用来计算 slist 中节点的个数,通过调用之前定义的全局函数 __slist_size 函数来实现。

  size_type size() const { return __slist_size(this->_M_head._M_next); }

empty 函数判断当前 slist 是否为空,通过查看 _M_head->next 是否为空指针可以得到。

  bool empty() const { return this->_M_head._M_next == 0; }

函数 swap 用来交换两个 slist。因为 slist 是由 _M_head 链接而成的,直接交换两个 slist 的 _M_head->_M_next (也可以直接交换 _M_head) 即可。

  void swap(slist& __x)
    { __STD::swap(this->_M_head._M_next, __x._M_head._M_next); }

函数 front 返回 slist 的第一个节点的数据内容。通过 _M_head->_M_next 得到指向第一个节点的指针,返回其成员 _M_data 的内容。

  reference front() { return ((_Node*) this->_M_head._M_next)->_M_data; }

函数 push_front 用来在 slist 的第一个节点之前插入一个新节点。通过调用 __slist_make_link 来实现。

  void push_front(const value_type& __x)   {
    __slist_make_link(&this->_M_head, _M_create_node(__x));
  }
  void push_front() { __slist_make_link(&this->_M_head, _M_create_node()); }

函数 pop_front 用来将 slist 的第一个节点删除,首先通过 _M_head 获得指向第一个节点的指针,并让 _M_head->_M_next 指向第二个节点。再将第一个节点中存储的数据内容销毁,最后回收第一个节点占用的内存。函数slist 是否为空进行判断。这就需要在调用该函数之前判断 slist 是否为空。

  void pop_front() {
    _Node* __node = (_Node*) this->_M_head._M_next;
    this->_M_head._M_next = __node->_M_next;
    destroy(&__node->_M_data);
    this->_M_put_node(__node);
  }

函数 previous 用来得到指定迭代器之前的一个迭代器。函数首先通过给定迭代器获取到指向链表中节点的指针 _M_node 。然后调用之前定义的全局函数 __slist_previous 得到指向之前节点的指针,并用该指针初始化一个迭代器,将这一个迭代器作为返回值返回。

  iterator previous(const_iterator __pos) {
    return iterator((_Node*) __slist_previous(&this->_M_head, __pos._M_node));
  }

函数 _M_insert_after 用来在给定位置之后插入一个新节点。函数首先构造一个新节点,然后调用 __slist_make_link 将构造的新节点通过 __slist_make_link 插入到给定位置 __pos 之后。

  _Node* _M_insert_after(_Node_base* __pos, const value_type& __x) {
    return (_Node*) (__slist_make_link(__pos, _M_create_node(__x)));
  }

  _Node* _M_insert_after(_Node_base* __pos) {
    return (_Node*) (__slist_make_link(__pos, _M_create_node()));
  }

函数 _M_insert_after_fill 用来在给定位置 __pos 之后插入 __n 个值为 __x 的元素,__slist_make_link 每次返回的是指向插入之后的新元素的指针。通过调用 __n 次 __slist_make_link 能将 __n 个值为 __x 的元素插入到 __pos 之后。

  void _M_insert_after_fill(_Node_base* __pos,
			    size_type __n, const value_type& __x) {
    for (size_type __i = 0; __i < __n; ++__i)
      __pos = __slist_make_link(__pos, _M_create_node(__x));
  }

_M_insert_after_range 函数中根据模板形参 _Inter 类型的不同,会调用 _M_insert_after_range 的两种不同定义。函数中用 _Inter 来实例化 _Is_Integer 以检测 _Inter 类型是否是整型,如果是,根据 _Is_Integer 的定义,_Integral 会是 _true_type 的类型别名,如果不是,则 _Integral 是 _false_type 的类型别名。

  template <class _InIter>
  void _M_insert_after_range(_Node_base* __pos, 
			     _InIter __first, _InIter __last) {
    typedef typename _Is_integer<_InIter>::_Integral _Integral;
    _M_insert_after_range(__pos, __first, __last, _Integral());
  }

函数 _M_insert_after_range 在给定位置 __pos 之后插入 __n 个值为 __x 的节点

  template <class _Integer>
  void _M_insert_after_range(_Node_base* __pos, _Integer __n, _Integer __x,
			     __true_type) {
    _M_insert_after_fill(__pos, __n, __x);
  }

函数 _S_insert_after_range 将 __first 到 __last 之间的内容插入到指定位置 __pos 之后。通过循环的调用 __slist_make_link 将 __first 到 __last 之间的内容插入到 slist 的 __pos 之后。__slist_make_link 每次的返回值是指向新插入节点的指针,这样能保证 while 循环中插入到 slist 中的节点顺序与从 __first 到 __last 的节点顺序是一致的。

  template <class _InIter>
  void _M_insert_after_range(_Node_base* __pos,
			     _InIter __first, _InIter __last,
			     __false_type) {
    while (__first != __last) {
      __pos = __slist_make_link(__pos, _M_create_node(*__first));
      ++__first;
    }
  }

函数 insert_after 是在给定迭代器 __pos 指向的节点的后面插入一个值为 __x 的新节点。__pos 的成员变量 _M_node 是指向节点的指针,则调用 _M_insert_after 将值为 __x 的新节点插入到 __pos._M_node 之后即可。函数的返回值为指向值为 __x 的新节点的指针。根据该指针构造一个新的迭代器作为函数的返回值。

  iterator insert_after(iterator __pos, const value_type& __x) {
    return iterator(_M_insert_after(__pos._M_node, __x));
  }

函数 insert_after 将一个用 value_type 类型的默认值构造的新节点插入到 __pos 之后。

  iterator insert_after(iterator __pos) {
    return insert_after(__pos, value_type());
  }

函数 insert_after 在给定迭代器 __pos 指向的节点之后插入 __n 个值为 __x 的节点。

  void insert_after(iterator __pos, size_type __n, const value_type& __x) {
    _M_insert_after_fill(__pos._M_node, __n, __x);
  }

函数 insert_after 将 __first 到 __last 之间的内容作为节点值构造新的节点,并将构造的新节点按照顺序插入到给定迭代器 __pos 指向的节点之后。

  template <class _InIter>
  void insert_after(iterator __pos, _InIter __first, _InIter __last) {
    _M_insert_after_range(__pos._M_node, __first, __last);   }

函数 insert 在给定的迭代器 __pos 指向的节点之前插入一个值为 __x 的新节点。 __pos._M_node 是指向节点的指针,调用 __slist_previous 得到一个指向 __pos._M_node 的前一个节点的指针。然后调用 _M_insert_after 可以将新节点插入到 __pos 指向的节点之前。

  iterator insert(iterator __pos, const value_type& __x) {
    return iterator(_M_insert_after(__slist_previous(&this->_M_head,
						     __pos._M_node),
		    __x));
  }

函数 insert 将用 vlaue_type 类型的默认值构造一个新节点插入到 __pos 指向的节点之前。

  iterator insert(iterator __pos) {
    return iterator(_M_insert_after(__slist_previous(&this->_M_head,
						     __pos._M_node),
				    value_type()));
  }

函数 insert 在 __pos 指向的节点之前插入 __n 个值为 __x 的新节点。借助 __slist_previous 和 _M_insert_after_fill 来实现。

  void insert(iterator __pos, size_type __n, const value_type& __x) {
    _M_insert_after_fill(__slist_previous(&this->_M_head, __pos._M_node),
			 __n, __x);
  } 

函数 insert 将 __first 到 __last 之间的元素作为节点值构造新节点。并将这些新节点插入到 __pos 指向的节点之前。

  template <class _InIter>
  void insert(iterator __pos, _InIter __first, _InIter __last) {
    _M_insert_after_range(__slist_previous(&this->_M_head, __pos._M_node), 
			  __first, __last);
  }

STL 的 slist 分析(一)</br> STL 的 slist 分析(二)</br> STL 的 slist 分析(三)</br> STL 的 slist 分析(四)</br> STL 的 slist 分析(五)</br>