zoukankan      html  css  js  c++  java
  • STL源代码剖析(二)

    提要

    先看一段用迭代器的代码:

    int a[] = {1, 2, 3, 4, 5};
    vector<int> v1( a, a+5);
    vector<int>::iterator iter = v1.begin( );	
    for (; iter != v1.end( ); ++iter)
    {
    	cout << *iter << " ";
    }
    cout<<endl;

    STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,批次独立设计,最后再以一帖胶水将它们撮合在一起。容器和算法的泛型化,从技术角度来看并不困难,C++的classtemplates和function templates可分别达成目标。

    迭代器模式定义:提供一种方法,使之能够依序寻訪某个容器所含的各个元素,而又无需暴露该聚合物的内部表达方式。




    function template的參数推导机制

    在算法中运用迭代器时。可能会用到其对应类型(associative type),即迭代器所指向对象的类别。

    但C++仅仅支持sizeof(),并不存在typeof()之说(即使运用RTTI性质中的typeid()获得的也仅仅是类型名称不能用来做变量声明之用)。
    为解决此问题。能够利用函数模板(function template)的參数推导(argument deduction)机制。仅将func函数作为一个包装。而把实际的操作放在一个函数func_impl里面完毕。一旦func()函数被调用。编译器就自己主动进行引数推导。自己主动导出类型T。

    template <class I, class T>
    void fun_impl(I iter, T t){     // 此处该函数利用模板參数推导得知T为*iter类型
        T tmp;                      // 能够声明变量
        //...
    };
    
    template <class I>
    inline void fun(I iter){
        fun_impl(iter, *iter); //此处把*iter作为第二个參数传递给fun_impl()
    }
    int main(int argc, char *argv[])
    {
        int i;
        fun(&i);
        return 0;
    }
    



    Traits编程技法

    traits技法使得泛型算法或者类的实现能够尽可能对模板參数提出小的要求。使用的方法就是建立一个与參数相关的traits类型,把參数对应的细节隐藏当中。


    偏特化(Partial Specialization)的意义 - 假设class template拥有一个以上的template參数。我们能够针对当中某个template參数进行特化工作。
    traits所扮演的“特性萃取机”角色,萃取各个迭代器的特性,这里所谓的迭代器特性指的是迭代器的对应类型。


    通过class template partial specialization的作用。不论是原生指针还是class-type iterators,都能够让外界方便地取得其对应类型。

    五种迭代器类型

    依据经验,最经常使用到的迭代器对应型别有五种:
    (1)value_type:
    是指迭代器所指对象的类型,是指STL容器内所存储的数据类型
    (2)difference_type:
    用来表示两个迭代器之间的距离。因此它也能够用来表示一个容器的最大容量。由于对于连续空间的容器,头尾之间的距离就是其最大容量。


    (3)pointer:
    (4)reference:
    从迭代器所指之物的内容是否同意改变的角度看,迭代器分为不同意改变所指对象的内容constant iterators和mutable iterators.
    (5)iterator_category:
    S依据移动特性和施行操作,迭代器可分为五种类型:
    Input Iterator:这样的迭代器所指对象,不同意外界改变。仅仅读。


    Output Iterator:仅仅写。


    Forward Iterator:同意“写入型”算法(比如replace())在此种迭代器所形成的区间上进行读写操作。


    Bidirectional Iterator:可双向移动。
    Random Access Iterator:前四种迭代器都仅仅供应一部分指针算术能力(前三种支持 operator++。第四种再加上 operator--)。第五种则涵盖全部指针算术能力,包含 p+n, p-n, p[n], p1-p2, p1<p2。


    总结

    设计适当的型别是迭代器的责任,实际适当的迭代器则是容器的责任。算法全然能够独立于容器和迭代器之外自行发展,仅仅要设计时以迭代器为对外接口就能够了。
    traits编程技法大量运用于STL实现中,它利用“内嵌类型”的编程技巧与编译器的參数推导功能,增强C++未能提供的关于型别认证方面的能力。弥补C++不为强类型语言的遗憾。

    參考

    <<STL源代码剖析>> 侯捷译

  • 相关阅读:
    ant design pro梳理
    JSON.stringify()
    数组小细节
    js this细节
    策略模式解决if-else过多
    使用useState的赋值函数异步更新问题
    Hook
    React Api
    Intent
    树的非递归遍历
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6934461.html
Copyright © 2011-2022 走看看