zoukankan      html  css  js  c++  java
  • 侯捷STL课程及源码剖析学习3: 深度探索容器list

    一、容器概览

    image

      上图为 GI STL 2.9的各种容器。图中以内缩方式来表达基层与衍生层的关系。所谓的衍生,并非继承(inheritance)关系,而是内含(containment)关系。例如 heap 内含一个 vector,priority-queue 内含一个 heap,stack  和 queue 都含一个 deque,set/map/multiset/multimap 都内含一个 RB-tree,hast_x都内含一个 hashtable. 

    二、序列式容器(sequential containers)

    所谓序列式容器,其中的元素都可序(ordered),但᳾排序(sorted)。C++  语 言本身提供了一个序列式容器array,STL另外再提供vector,list,deque, stack,queue,priority-queue等等序列式容器。其中stack和queue由于 只是将deque改头换面而成,技术上被归类为一种适配(adapter)。

    list 容器

    文件依赖结构图

    DependsOn-list

    list概览

    image

    list 内实现了其迭代器(G2.9)

    image

    注意操作符++重载

    image

      虽然iterator也重载operator*(), 但是这里面的*this并没有使用这个重载;例如self tmp = *this, return *this;这两次*this已经被解释为拷贝构造的参数了 ++*this也没有使用重载的operator*();也是已经把*this解释成了operator++()的参数了 

    简化修改代码

      1 #include <iostream>
      2 #include <cstdio>
      3 namespace sk
      4 {
      5     template <class T>
      6 struct __list_node {
      7   typedef void* void_pointer;
      8   void_pointer next;
      9   void_pointer prev;
     10   T data;
     11 };
     12 
     13 template<class T, class Ref, class Ptr>
     14 struct __list_iterator {
     15   typedef __list_iterator<T, T&, T*>             iterator;
     16   typedef __list_iterator<T, const T&, const T*> const_iterator;
     17   typedef __list_iterator<T, Ref, Ptr>           self;
     18 
     19   typedef T value_type;
     20   typedef Ptr pointer;
     21   typedef Ref reference;
     22   typedef __list_node<T>* link_type;
     23   typedef size_t size_type;
     24 
     25   link_type node;
     26 
     27   __list_iterator(link_type x) : node(x) { printf("__list_iterator(link_type x) 
    "); }
     28   __list_iterator() { printf("__list_iterator() 
    "); }
     29   __list_iterator(const iterator& x) : node(x.node) {printf("__list_iterator(const link_type x) 
    ");}
     30 
     31   bool operator==(const self& x) const { return node == x.node; }
     32   bool operator!=(const self& x) const { return node != x.node; }
     33   reference operator*() const {  printf(" operator*() 
    ");return (*node).data; }
     34 
     35 #ifndef __SGI_STL_NO_ARROW_OPERATOR
     36   pointer operator->() const { return &(operator*()); }
     37 #endif /* __SGI_STL_NO_ARROW_OPERATOR */
     38 
     39   self& operator++() {
     40       printf("prev ++ 
    ");
     41     node = (link_type)((*node).next);
     42     return *this;
     43   }
     44   self operator++(int) {
     45        printf("post ++ 
    ");
     46     self tmp = *this;
     47     ++*this;
     48     return tmp;
     49   }
     50   self& operator--() {
     51     node = (link_type)((*node).prev);
     52     return *this;
     53   }
     54   self operator--(int) {
     55     self tmp = *this;
     56     --*this;
     57     return tmp;
     58   }
     59 
     60    void operator=(const self &test)
     61      {
     62          printf("operator=
    ");
     63 
     64      }
     65 };
     66 
     67 }
     68 
     69 typedef sk::__list_iterator<int,int&,int*> 
     70     list_iterator_int;
     71 list_iterator_int 
     72 testassign(list_iterator_int t)
     73 {
     74     return t;
     75 }
     76 
     77 int main()
     78 {
     79     sk::__list_node<int> node1;
     80     sk::__list_node<int> node2;
     81     sk::__list_node<int> node3;
     82     sk::__list_node<int> node4;
     83     sk::__list_node<int> node5;
     84     node1.next = &node2;
     85     node2.next = &node3;
     86     node3.next = &node4;
     87     node4.next = &node5;
     88 
     89     node2.prev = &node1;
     90     node3.prev = &node2;
     91     node4.prev = &node3;
     92     node5.prev = &node4;
     93 
     94     sk::__list_iterator<int,int&,int*> iter1;
     95     iter1.node = &node2;
     96     printf("-------------------iter1++----------------------
    ");
     97     iter1++;
     98     printf("-------------------++iter1----------------------
    ");
     99     ++iter1;
    100     printf("
    ");
    101     printf("-------------------1----------------------
    ");
    102     list_iterator_int iter_test;
    103     printf("-------------------2----------------------
    ");
    104     iter_test = iter1;
    105     printf("-------------------3----------------------
    ");
    106     list_iterator_int iter2 = iter1;
    107     printf("-------------------4----------------------
    ");
    108     iter_test = testassign(iter1);
    109     printf("-------------------5----------------------
    ");
    110     testassign(iter1);
    111     printf("------------------------------------------
    ");
    112 
    113     return 0;
    114 }
    test

    测试结果

    image

    • 传参的过程中,要调用一次复制构造函数:   iter1入栈时会调用复制构造函数创建一个临时对象,与函数内的局部变量具有相同的作用域.
    • 函数返回值时,也会构造一个临时对象;调用重载赋值操作符赋值给iter_test.

    内容参考整理:侯捷STL课程

  • 相关阅读:
    ASP.NET页面事件执行过程 总结
    程序员最应该读的图书(中译版) [收藏]
    C# 中的委托和事件的详解资料
    已添加项。字典中的关键字
    TFS 删除团队项目集合
    注册后第一篇
    类型的权限已失败 SqlClientPermission
    C#创建Oracle存储过程
    使用MySQL with 递归查询菜单树
    MySQL 常用TSQL(持续更新...)
  • 原文地址:https://www.cnblogs.com/flysong/p/8158015.html
Copyright © 2011-2022 走看看