STL之list(一)

       list概述

       相对于vector的连续性空间,list就显的复杂许多,它的好处是每次安插或删除一个元素,就配置或释放一个元素空间。因此,list对于空间的运用有绝对的精确,一点也不浪费。而且,对于任何职位的元素安插或元素移除,list永远是常数时间。

       list和vector是两个最常使用的容器。什么时机下最合适使用哪一种容器,必须视元素的多寡,元素的构造复杂度,元素存取行为的特性而定。

       list的节点

       list本身和list的节点是不同的结构,需要分开设计,以下是STL list的节点node结构:   

template <class T>
struct __list_node
{
  typedef void* void_pointer;
  void_pointer next;
  void_pointer prev;
  T data;
};

      list的迭代器

      list不在能够像vector一样以原生指标作为迭代器,因为其节点不保证在存储空间中连续存在。list迭代器必须有能力指向list的节点,并有能力做正确的递增,递减,取值,成员存取...等动作。STL list是一个双向串行,迭代器必须具备迁移,后移的能力。所以list提供的是Bidirectional Iterators。

      list有一个重要性质:安插动作(insert)和接合动作(splice)都不会造成原有的list迭代器失效。这在vector是不成立的,因为vector的安插动作可能造成记忆体重新配置,导致原有迭代器全部失效。甚至list的元素删除动作erase,也只有(指向被删除元素)的那个迭代器失效,其它迭代器不受影响。      

// 至于为什么不使用默认参数, 这个是因为有一些编译器不能提供推导能力,
// 而作者又不想维护两份代码, 故不使用默认参数
template<class T, class Ref, class Ptr>
struct __list_iterator
{
  // 标记为'STL标准强制要求'的typedefs用于提供iterator_traits<I>支持
  typedef __list_iterator<T, T&, T*>             iterator;   // STL标准强制要求
  typedef __list_iterator<T, const T&, const T*> const_iterator;
  typedef __list_iterator<T, Ref, Ptr>           self;

  typedef bidirectional_iterator_tag iterator_category;
  typedef T value_type;                                 // STL标准强制要求
  typedef Ptr pointer;                                  // STL标准强制要求
  typedef Ref reference;                                // STL标准强制要求
  typedef __list_node<T>* link_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;                    // STL标准强制要求

  // 这个是迭代器实际管理的资源指针
  link_type node;

  __list_iterator(link_type x) : node(x) {}
  __list_iterator() {}
  __list_iterator(const iterator& x) : node(x.node) {}

  // 在STL算法中需要迭代器提供支持
  bool operator==(const self& x) const { return node == x.node; }
  bool operator!=(const self& x) const { return node != x.node; }

  // 重载operator *, 返回实际维护的数据
  reference operator*() const { return (*node).data; }

#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */

  // 前缀自加
  self& operator++()
  {
    node = (link_type)((*node).next);
    return *this;
  }

  // 后缀自加, 需要先产生自身的一个副本, 然会再对自身操作, 最后返回副本
  self operator++(int)
  {
    self tmp = *this;
    ++*this;
    return tmp;
  }

  self& operator--()
  {
    node = (link_type)((*node).prev);
    return *this;
  }

  self operator--(int)
  {
    self tmp = *this;
    --*this;
    return tmp;
  }
};

         list的数据结构

        list不仅是一个双向串行,而且还是一个环状双向串行。所以它只需要一个指标,便可以完成表现整个串行。如果让指标node指向可以置于尾端的一个空白节点,node便能符合STL对于[前闭后开]区间的要求,成为last迭代器,如下图所示:




### C++ STL List 容器删除元素 #### 使用 `erase` 函数 对于C++ STL中的`list`容器,可以使用成员函数`erase`来移除指定位置的元素。此函数接受迭代器作为参数并删除该迭代器指向的位置上的项目[^2]。 ```cpp #include <iostream> #include <list> int main() { std::list<int> myList = {1, 2, 3, 4, 5}; // 创建个迭代器指向第三个元素 (即值为3) auto it = myList.begin(); advance(it, 2); // 删除第三个元素 myList.erase(it); // 输出剩余列表项 for(auto& elem : myList){ std::cout << elem << " "; } } ``` 上述代码展示了如何通过创建指向目标位置的迭代器,并将其传递给`erase`来进行单个元素的移除操作。 #### 移除最后面的个元素 要从`list`中去除最末端的项,则可以直接调用`pop_back()`方法实现这点。实际上,在某些标准库实现在内部会利用`erase`配合`end()`来完成这功能。 ```cpp std::list<int>::iterator popBackExample(std::list<int>& lst) { if (!lst.empty()) { return lst.erase(--lst.end()); } return lst.end(); // 如果为空则返回结束迭代器 } ``` 这段例子说明了当执行`pop_back`时发生的实际过程:先定位到最后个有效元素之前的位置再做清除处理。 #### 清空整个链表 如果目的是清空整个`list`对象内的全部内容,那么应该采用`clear()`成员函数;这将高效地释放所有关联资源而不必逐遍历各个节点去单独销毁它们[^1]。 ```cpp myList.clear(); ``` 以上就是几种常见的用于管理`list`内存储单元生命周期的操作手段介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值