C++ primer超详细讲解泛型算法
初识泛型算法只读算法只读取输入范围内的函数不改变元素findaccumula也是如此1accumulate算法为求和算法前两个参数指出求和元素范围第三个是和的初值例int sumaccumulate(v.begin(),v.end(),0)2操作两个序列的算法equal算法确定两个序列是否保存相同的值将第一个序列的每个元素和第二个序列中的每个元素进行比较若相同返回true否则返回false接受三个参数前两个表示第一个序列的元素范围第三个表示第二个序列的首元素equal(r1.begin(),r1.end(),r2.begin())写容器算法1拷贝算法向另一个目的位置迭代器指向的输出序列中的元素写入数据算法。此算法接受三个迭代器前两个表示一个舒服范围第三个表示目的序列的起始位置。copy返回目的迭代器的值。123inta1[] { 0,1,2,3,4,5 };inta2[sizeof(a1) /sizeof(*a1)];auto ret copy(begin(a1), end(a1), a2);定制操作lambda表达式1定义一个lambda表达式表示一个可调用的代码单元可理解为未命名的内联函数lambda表达式形式[capture list](parameter list) - return type{function body}可以忽略参数列表和返回类型但必须永远包含捕获列表和函数体auto f [] {return 42}调用: coutf()endl;2向lambda传递参数实参被用来初始化lambda的形参lambda不能有默认参数例123//[](const string a,const string b){return a.size()b.size()}//调用sort(w.begin(),w.end(),[](conststring a,conststring b){returna.size()b.size()})(3)使用捕获列表一个lambda通过将局部变量包含在其捕获列表中指出将会使用这些变量捕获列表指引lambda在其内部包含访问局部变量所需的全部信息例如找出第一个大于等于给定长度的单词。函数biggies实现12345voidbiggies(vectorstring words,vectorstring::size_type sz){auto wcfind_if(words.begin(),words.end(),[sz](conststring a){returna.size()sz});}lambda捕获和返回1值捕获与传值参数类似采用值捕获的前提是变量可以拷贝与参数不同被捕获的变量的值是在lambda创建时拷贝而不是调用时拷贝1234567voidfcun(){size_tv142;auto f[v1]{returnv1;};v10;auto jf();}由于被捕获变量的值是在lambda创建时拷贝因此随后对其修改不会影响到lambda内对应的值上述中j的值为422引用捕获1234567voidfcun(){size_tv142;auto f[v1]{returnv1;};v10;auto jf();//j为0f2保存v1的引用而非拷贝}3隐式捕获可以让编译器根据lambda体中的代码推断我们要使用哪些变量此时应在捕获列表中写一个或表示采用捕获引用表示采用值捕获方式。1wcfind_if(w.begin(),w.end(),[](conststring s){returns.sizesz;});(4)可变lambda在值拷贝的情况下lambda不会改变其值若希望能够改变被捕获的变量的值则在参数列表首加上mutable关键字。1234567voidfunc(){size_tv142;auto f[vi]()mutable{returnv1;};v10;auto jf();}一个引用捕获的变量能否可以修改依赖于此引用指向的是一个const还是非const类型1234567voidfc(){constsize_tv1 42;auto f [v1]()mutable{returnv1; };//无法修改v1auto j f();cout j endl;}5指定lambda的返回类型默认情况下如果一个lambda体中包含return之外的任何语句则编译器假定此lambda返回void。例如将一个序列中负数替换为其绝对值1transform(v.begin(),v.end(),v.begin(),[](inti){returni0?-i:i;})transform接受三个参数前两个表示迭代器输入序列第三个表示迭代器目的位置。上述中我们无需指定返回类型因此可以根据条件运算符的类型推断出来。若改写成存在if语句则存在错误1transform(v.begin(),v.end(),v.begin(),[](inti){if(i0)return-i;elsereturni;})编译器发现存在return之外的语句所以推断其返回类型为void而他却返回了一个int正确写法12transform(v.begin(),v.end(),v.begin(),[](inti) -int{if(i0)return-i;elsereturni;})再探迭代器标准库头文件iterator中还定义了额外几种迭代器包括如下插入迭代器绑定到一个容器上向容器插入元素流迭代器绑定到输入输出流上可以用来遍历所关联的IO流反向迭代器这些迭代器向后而不是向前移动forwar_list不存在此迭代器移动迭代器移动元素专用