C++primer 第十章笔记 初稿

10.1概述

  1. 大多数定义在头文件里,部分数值泛型算法定义在里。

  2. 算法不依赖于容器类型,但依赖于元素类型操作(即关系运算)。

  3. 对于内置数组,可以使用 begin(数组名)、end(数组名)来获取对应指针,使算法对内置数组进行类似容器的处理。

  4. 算法并不真正执行容器本身操作,一切操作都基于迭代器。

10.2简单泛型算法的使用

  1. 只读算法

    • count

      • 接收:一对迭代器和一个值。
      • 返回:该值出现的次数。
    • find

      • 接收:一对迭代器和一个值。
      • 返回:迭代器。
    • accumulate

      • 接收:一对迭代器和一个初值。
      • 返回:累加求和结果。
      • 误区:string可以实现,但const char* 不可以实现。
    • equal

      • 接收:第一个序列的一对迭代器和第二个序列的首迭代器。
      • 返回:true/false。
      • 误区:string可以实现,但const char* 不可以实现。
  2. 写算法

    • fill

      • 接收:一对迭代器和一个用于赋值的值。
    • fill_n

      • 接收:一个迭代器表示开始位置,一个值表示赋值个数,一个值用于赋值。
      • 误区:不能给空容器赋值。
    • back_inserter

      • 头文件:iterator
      • 功能:向容器末尾插入元素(结合fill_n可解决空容器问题)。
      • 例子
        vector<int>vec;
        auto it=back_inserter(vec);
        fill_n(it,10,0);
  3. 重排算法
    • unique
      • 接收:一对迭代器。
      • 返回:指向重排后不重复区域后一个位置的迭代器。
      • 和erase方法配套可以去重。

10.3 自定义操作

  1. 谓词:一个可调用的表达式,返回结果为一个能用作条件的值,分一元谓词与二元谓词(也就是自定义取代默认操作符)。

  2. 可调用对象

    • 定义:可以对其使用调用运算符(())的对象或表达式。
    • 包括:函数与函数指针、重载函数调用运算符的类、lambda表达式。
  3. lambda表达式

    • 定义:可调用的代码单元,类似于未命名的内联函数,格式为:
      [capture list](parameter list)>return type {function body}
    • 特点:
      • 可定义在函数内部。
      • 必须使用尾置返回,但返回类型与参数列表可忽略,同时自动推断返回类型(若包含单一return之外的语句则返回void)。
      • 不能有默认参数。
    • 例子

      auto f = [](const string &a, const string &b)
          {return a.size() < b.size();};
      stable_sort(s.begin(), s.end(), f());

      或者直接

      stable_sort(s.begin(), s.end(),
                  [](const string &a, const string &b)
                  {return a.size() < b.size();});
    • 捕获方式:

      • 显示捕获
        • 值捕获
          • 如果想在lambda表达式中改变该值,须在参数列表后,表达式体前加关键字 mutable。
        • 引用捕获
      • 隐式捕获:只写明捕获方式而不写明捕获的具体对象。
  4. 函数替代lambda表达式

    • 思路:运用bind函数

    • bind函数

      • 头文件:functional
      • 一般形式:
        auto newCallable=bind(callable, arg_list)

        其中callable为相关函数,arg_list为逗号分隔的 参数列表。
    • arg_list
      • _n:占位符,表示绑定函数的第n个参数。
      • 通常为_n与实参混合使用。
      • 其中_n必须显示声明using namespace std::placeholders。
      • 一个巧妙运用

        sort(words.begin(), words.end(), bind(isShorter, _2, _1));
      • 运用ref()函数绑定参数实现引用传递。

10.4 头文件中的迭代器

  1. 插入迭代器:back_inserter、front_inserter、inserter。

  2. IO迭代器:

    • istream_iterator

      • 如果绑定流则从流的第一个位置开始,不绑定则为尾后位置。
      • 辅助创建容器

        istream_iterator<int>in(cin),eof;
        vector<int>v(in,eof);
      • 迭代器被解引用时才真正从流中读取数据。

    • ostream_iterator

      • 通过绑定的可以为每次输出附加一个固定输出。
      • 辅助容器输出(推荐未注释的方法)
            for(auto e : v)
                out = e;
        //  for(auto e : v)
        //      *out++ = e;
        //  copy(v.begin(), v.end(), out); 
  3. 反向迭代器
    会出现倒序输出的情况(有时来说是个问题),可以使用base()方法使反向迭代器转化为普通迭代器。

10.5 泛型算法结构

  1. 五类迭代器(层次由低到高)

    • 输入迭代器

      • 支持 ==、!=
      • 支持前置、后置自增
      • 支持解引用*与->运算符
      • 只能用于单遍扫描,可支持算法find、accumulate,istream_iterator是输入迭代器。
    • 输出迭代器

      • 输入迭代器的补集
      • 支持前置、后置自增
      • 支持解引用运算符
      • 出现在赋值运算符的左侧
      • 支持copy的第三个参数,ostream_iterator是输出迭代器
    • 前向迭代器
      • 输入输出迭代器的并集
      • 支持replace算法,forward_list的迭代器是前向迭代器
    • 双向迭代器
      • 支持前置、后置自减运算符
      • 支持reverse算法
    • 随机访问迭代器
      • 比较运算符
      • 单迭代器的加减运算符
      • 两个迭代器的减运算符
      • 下标运算符
      • 支持sort,array,deque,string,vector都是随机访问迭代器,内置数组的指针也是。
  2. 接收单个目标迭代器的算法,一般可以用输入迭代器代替写入目的位置的迭代器以保证安全。

  3. 算法命名规范

    • 一些算法使用重载,接收谓词来代替==或<运算符。
    • _if版本的算法,通过谓词来代替元素值。
    • 一些算法增加_copy版本把新的结果存储到其他容器中
  4. 链表的特定算法

    • merge:分治合并(有重载的谓词版本)
    • remove:删除元素(有remove_if的谓词版本)
    • reverse、sort、unique
    • splice:将一个链表的一部分移动到另一个链表中,其中若调用者为双向链表,则移动到位置之前,否则为位置之后。
    • 链表特有的算法会改变底层容器。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值