C++源码剖析与泛型编程(侯捷)(七) 算法

C++标准库的算法,是什么东西?

从语言层面上讲:

  • 容器Container是个class template
  • 算法Algorithm是个function template
  • 迭代器Iterator是个class template
  • 仿函数Functor是个class template
  • 适配器Adapter是个class template
  • 分配器Allocator是个class template

算法看不见容器,对其一无所知;所以,它所需要的一切信息都必须从Iterators取得,而Iterators(由容器提供)必须能够回答Algorithm的所有提问,才能搭配该Algorithm的所有操作。

 迭代器的分类

不连续空间的容器迭代器都是不能跳的,比如List的迭代器是bidirectional_iterator_tag,Forward_LIst的迭代器是Forward_iterator_tag

输入迭代器、输出迭代器、正向迭代器、双向迭代器、随机访问迭代器(描述了移动方式)

由每种容器的内存分布特性可推断其迭代器类型:

    Array Vector Deque: 随机访问迭代器。
    List Set Map(rb_tree):双向迭代器(红黑树节点之间是双向链接)。
    Forward List:正向迭代器。
    Unordered Set Map:由其底部实现的哈希表中的链表决定,可能为正向或者双向迭代器。

    不同类型的迭代器是不同的类,上例可以通过函数重载写成不同的函数(_display_category())。

array<int,10>::iterator(),这里的前面是一个类型,类型+()是代表产生一个临时对象的意思。

    不同版本标准库中的istream_iterator的iterator_category接口一样。对于自己迭代器的定义式input_iterator_tag/output_iterator_tag。

    父类只是一些typedef,没有data,没有function,继承只是为了拥有这些typedef。

1.迭代器对算法的影响

之所以不用类型12345来区分,而是用对象的方式,一是_display_category调用时可以直接重载,而若是类型12345,则无法做到这样(这个原因略牵强);二是在算法实现时可以用上多态特性,而不必为每个类型写一个函数。

distance算法

distance用来知道两个指针间的距离。

distance函数时一般由其他算法调用的,而不是用户调用。

返回类型是traits中的difference_type(5个相关类型)而不是int之类的类型。

这种由一个主函数调用不同情况下的 iterator 重载次函数的形式,广泛存在与 STL 算法中。

因为 iterator_tag 具有继承关系的类,所以所有的类型情况都可以 只提供几种方案并利用多态来实现

advance算法

advance 函数为 iterator 向前操作,参数为 iterator 引用分3种情况利用多态实现了所有迭代器类型的操作

Copy算法

传递的三个参数:来源端的起止点和目的端的起点。

不断的检查,根据不同类型进行不同的处理。

  • 一般 iterator 时,每复制过一个元素都要检查是否到头,效率较低。
  • random_acess_iterator 时,根据黄字,可直接判断循环次数,效率较高。(随机访问表示连续内存分布)。
  • trival op = 与 non_trival op= 如何判断:例如,复数类,只有两个元素 im 和 re ,没有指针,这样的类不需要写析构、拷贝构造、拷贝赋值函数,编译器默认生成的这些函数就是 non_trival 的。(第四讲  STL 之外,标准库之内的东西,比如traits)

input_iterator和output_iterator的不同

这就是容器的迭代器为什么要回答5个问题,根据不同类型做出不同的处理。

 调用第一行编译是会通过的,因为它毕竟是个模板,需要接受所有的类型(继承类型),然而当到跳的那一步是还是会失败。

算法中的源码剖析

形如以下形式的接口才是C++标准库的算法:

template<typename Iterator>
std::Algorithm(Iterator itr1,Iterator itr2,...)
{
     ....
} 

accumulate

accumlate 算法有两种重载的形式默认为累加,其中第二种接收一个自定义操作对数据做累计。

myobj() 表示函数对象(或称仿函数),实质是一个类或者结构体,重载了 operator()

for(decl:coll){   //decl是变量声明,coll是一堆东西
    statement
}

算法replace,replace_if,replace_copy  命名带if的会带一个条件。

这8个就是关联性容器,可以由key找到value,因此它们有自己比较快的算法。(没有sort是因为存完后就排序好了)

标准库中的sort是需要迭代器可以随便跳的,所以List和forward_list是不可以用的。

rbegin() 通过 适配器reverse iterator 调整 end() 得到

算法binary_search

必须是一个排序序列才可以使用binary_search。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值