十、泛型算法

一、概述

1、大多数算法都定义在头文件algorithm中;头文件numeric中定义了一组数值泛型算法

2、一般情况下,这些算法并不直接操作容器,而是遍历两个迭代器指定的一个元素范围

  • 算法永远不会改变底层容器的大小,想要改变必须使用容器自带的操作

二、初识泛型算法

1、理解算法最基本的方法是了解他们是否读取元素、改变元素或是重排元素顺序

2、那些只接受一个单一迭代器来作为第二个序列的算法,都假定第二个序列至少与第一个序列一样长

三、定制操作

1、一元谓词:只接受单一参数;二元谓词:有两个参数

2、lambda表达式:一个可调用的代码单元:一个未命名的内联函数

  • [capture list](parameter list) –> return type { function body }
    • capture list:捕获列表:lambda所在函数中定义的局部变量的列表(通常为空)
    • lambda必须使用尾置返回来指定返回类型:如果只有包含return意外的语句,默认返回void,所以就必须自己指定返回类型;
    • 可以忽略参数列表和返回类型,但是必须包含捕获列表和函数体
      • auto f = [] {return 42;};
    • lambda不能有默认参数
    • 一个lambda只有在其捕获列表中捕获一个它所在函数中的局部非static变量,才能在函数体中使用该变量;可以直接使用局部static变量和它所在函数之外声明的名字
    • 变量的捕获方式也可以是值或引用;如果是引用捕获一个变量时,必须保证在lambda执行时变量存在
    • 一般,我们应该减少捕获的数据量,来避免潜在的捕获导致的问题;而且,可能的话,应该避免捕获指针和引用
    • 可以通过编译器根据lambda体中的代码来推断捕获的变量:隐式捕获
      • &:采用捕获引用方式;
      • =:采用值捕获方式;
      • 当混合使用隐式和显式捕获时,捕获列表中的第一个元素必须是一个&或=;且显式捕获的变量必须使用与隐式捕获不同的方式

3、参数绑定:可以把一个接受很多参数的函数绑定一个可调用的对象,来满足算法对一元谓词的要求

  • auto newCallable = bind(callable, arg_list);
  • for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' '));
    • _1为print的第一个参数,其他为默认参数

4、lambda和函数:

  • 如果只有在一个两个地方使用的简单操作,lambda表达式最有效,如果需要多个地方使用相同的操作,通常应该定义一个函数
  • 如果lambda的捕获列表为空,通常可以用函数来代替他
  • 如果一个操作需要很多语句才能完成,通常使用函数

四、迭代器

1、插入迭代器:实现向给定容器添加元素

  • back_inserter:创建一个使用push_back的迭代器
  • front_insert:创建一个使用push_front的迭代器
  • inserter:创建一个使用insert的迭代器
    • inserter(c, iter)
      • c为要插入的容器,iter为给定的迭代器:元素被插入到给定迭代器锁表示的元素之前

2、流迭代器:绑定到输入或输出流上,用来遍历关联的IO流

3、反向迭代器:通过调用rbegin、rend、 crbegin、和cend成员函数来获得反向迭代器

  • 只能从既支持++也支持--的迭代器来定义反向迭代器
  • 不可能从forward_list或流迭代器创建反向迭代器

4、移动迭代器:不拷贝而是移动它们,13.6.2介绍

posted @ 2015-10-07 20:18  dylqt  阅读(194)  评论(0编辑  收藏  举报