CppPrimer笔记 Chapter10 泛型算法

来源:互联网 发布:小鸟云服务器知乎 编辑:程序博客网 时间:2024/06/06 04:09

CppPrimer笔记 Chapter10 泛型算法

标签: Cpp


  • CppPrimer笔记 Chapter10 泛型算法
    • 概述101
    • 初识泛型算法102
    • 向算法传递函数1031
    • lambda表达式1032-1033
    • 参数绑定1034
    • 迭代器104
    • 5类迭代器1051
    • 特定容器算法106
    • 移动迭代器P480


概述(10.1)

  • find(vec.it1,vec.it2,val);[it1,it2)中寻找val,找到则返回指向的容器,没找到则返回it2
  • 算法永远不会执行容器操作,即添加,删除元素.其值运行于迭代器上.利用一般的迭代器,可以改变容器中的值,移动元素.利用特殊的迭代器插入器可以进行插入操作,但这时给这类迭代器赋值时迭代器自己进行的,而不是算法进行的.

初识泛型算法(10.2)

  • accumulate(v.cbegin(),v.cend(),0)第三个参参数作为求和起点,隐含着序列中元素与这个参数可以相加
  • equal(roster1.cbegin(),roster1.cend(),roster2.cbegin())判断roster1是否与roster2的前roster1.size()个相等,隐含了第二个序列至少与第一个一样长
  • back_inserter 接受一个指向容器的引用,返回一个与该容器绑定的插入迭代器,向该迭代器赋值即调用push_back将一个具有给定值的元素添加到容器中
  • 常用函数示例
    vector<int> vec;    fill_n(back_inserter(vec), 15, 1);//添加15个1到vec    fill_n(vec.begin(), 5, 0);//将vec前5个换为0    int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };    auto ret = copy(begin(arr), end(arr), vec.begin());//将arr值拷贝到vec中    //vec = {0,1,2,3,4,5,6,7,8,9,1,1,1,1,1}    if (ret == vec.end()){ cout << "re == vec.end" << endl; }//true    replace(vec.begin(), vec.end(), 1, 10);//将vec中1换成10    //vec = {0,10,2,3,4,5,6,7,8,9,10,10,10,10,10}    vector<int> vec2;    replace_copy(vec.cbegin(), vec.cend(), back_inserter(vec2), 10, 1);//将vec中10换成1后赋值给vec2,而原vec不变
  • 利用sortunique排序后删去重复元素
void elimDups(vector<string> &words){    sort(words.begin(), words.end());    auto end_unique = unique(words.begin(), words.end());    words.erase(end_unique, words.end());}

向算法传递函数(10.3.1)

  • stable_sort(words.begin(), words.end(), isShorter);按照isShorter()规定的规则来排序,同时stable_sort保持相等元素的原有顺序
  • 上行代码中isShorter是一个谓词,需满足严格弱序

lambda表达式(10.3.2-10.3.3)

  • lambda表达式格式[capture list](parameter list) -> return type{function body} 表示一个可调用的代码单元,我们可以将其理解为一个未命名的内联函数
  • lambda不能有默认参数
  • lambda包含return之外的任何语句,则编译器假定此lambda返回void

  • 定义lambda时,生成一个与lambda对应的新的未命名类类型.默认情况下,生成的类都包含一个所捕获变量的数据成员,在lambda对象创建时被初始化(而不像函数一样,在调用时拷贝)

  • 尤其注意引用拷贝时引用,指针,迭代器的有效性
  • 使用mutable使得按值捕获的lambda表达式可以修改被捕获变量的值

参数绑定(10.3.4)

  • 利用using std::placeholders来使用_n进行形参占位
  • auto newCallable = bind(callable,arg_list);来进行绑定,利用_n进行形参占位,从而被占位的形参达到像变量捕获的效果
  • auto g = bind(f,a,b,_2,c,_1)回想g(arg1,arg2)映射为f(a,b,arg2,c,arg1)`
  • youyu bild那些非占位符参数被拷贝到bind返回的可调用对象中,因而若要按引用传递,则必须使用ref()bind(print,ref(os),_1)

迭代器(10.4)

  • 插入迭代器
    vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };    auto iter = vec.begin() + 5;//*iter = 6    auto it_in = inserter(vec, iter);    *it_in = 20;    //vec = {1 2 3 4 5 20 6 7 8 9 10}    //*iter;//error 参见 顺序容器 插入后迭代器的有效性问题    *it_in = 30;    //vec = {1 2 3 4 5 20 6 7 8 9 10}    list<int> lst = { 1, 2, 3, 4 };    list<int> lst2, lst3;    copy(lst.cbegin(), lst.cend(), front_inserter(lst2));    //lst2 = {4,3,2,1}
  • 流迭代器:被绑定到输入或输出流上,可用来便利所关联的IO流
    • 在第一次解引用迭代器时才真正读取
    • istream_iterator默认初始化,可以当做尾后值使用
    • 不支持递减运算
    //将in_iter绑定在cin上,其为指向输入流数据的一个容器    //eof默认初始化,可以当做尾后值使用    istream_iterator<int> in_iter(cin),eof;    while(in_iter != eof)    //先解引用,然后指向下一个数字    vec.push_back(*in_iter++);        vector<int> vec2{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };    ostream_iterator<int> out_iter(cout, " ");    for (auto e:vec2)    {        *out_iter++ = e;    }    cout << " :out" << endl;    //输出 1 2 3 4 5 6 7 8 9 10  :out
  • 反向迭代器
    • sort(vec.rbegin(),vec.rend());将最小元素放在vec的末尾
  • 移动迭代器P480

5类迭代器(10.5.1)

  • 输入迭代器
  • 输出迭代器
  • 前向迭代器
  • 双向迭代器
  • 随机访问迭代器

特定容器算法(10.6)

  • 链表特有的操作会改变容器

移动迭代器P480

0 0
原创粉丝点击