只读算法
(1)accumulate返回容器的和
int sum = accumulate(vec.cbegin(),vec.cend(),0);
string sum = accumulate(v.cbegin(),v.cend(),string(""));//注意第三个参数不接受"",因为const char*类型没有重载“+”会编译错误
(2)equal比较两个等长的容器(元素个数相同)是否保存相同的值
equal(vec1.cbegin(),vec1.cend(),vec2.cbegin());
写容器元素算法
(1)fill填充元素值
fill(vec.begin(),vec.end(),0);
(2)back_inserter接收一个容器的引用,返回该容器的插入迭代器,可以做插入容器操作
vector<int> vec;
auto it = back_inserter(vec);
*it = 42; //vec中有42
vector<int> vec;
fill_n(back_inserter(vec),10,0); //添加10个元素到vec
(2)copy复制数组
int a1[] = {0,1,2,3,4,5,6};
int a2[sizeof(a1)/sizeof(*a1)];
auto ret = copy(begin(a1),end(a1),a2);
(3)replace将容器内指定值置换成另一个值
replace(vec.begin(),vec.end(),0,42); //0换成42;
(4)replace_copy如果不想改变原数组可以使用这个,得到置换后的新数组
vector<int> newvec;
replace_copy(vec.begin(),vec.end(),back_inserter(newvec).0,42);
消除重复单词算法
void elimDups(vector<string>& words)
{
sort(words.begin(),words.end());
auto end_unique = unique(words.begin(),words.end());
words.erase(end_unique,words.end());
}
lambda表达式
(1)标准写法
[capture list](parameter list) -> return type { function body}
我们可以忽略参数列表和返回类型,但是永远包含捕获列表和函数体
vector<int> vec;
sort(words.begin(),words.end(),[](const string& a,const string& b){return a.size()<b.size();}}
(2)捕获列表
捕获列表中的参数捕获该函数所在的局部变量,然后在lambda表达式中可以直接进行使用,而参数列表是外部调用的时候传入的参数。
//获取一个迭代器,指向第一个满足size()>=sz的元素
auto wc = find_if(words.begin(),words.end(),[sz](const string& a){return a.size() >= sz}};
//打印长度大于等于给定值的单词,每个单词后面接一个空格
for_each(wc,words.end(),[&os](const string& s){cout<<s<<"";});
(3)隐式捕获和显示捕获
当我们混合喜欢使用隐式捕获和显示捕获时,显示捕获的变量必须使用与隐式捕获不同的方式。即,如果隐式捕获是引用方式,则显示捕获命名变量必须采用值方式,因此不能在其名字前使用&。类似的,如果隐式捕获采用的是值方式,则显示捕获命名变量必须。
(4)可变mutable
默认情况下,对应一个值被拷贝的变量,lambda不会改变其值。如果我们希望能改变一个被捕获的变量的值,就必须在参数列表首加上关键字mutable。因此,可变lambda能省略参数列表:
void fcn3()
{
size_t v1 = 42;
auto f = [v1]()mutable{ return ++v1};
v1 = 0;
auto j = f(); //j = 43;
}
(5)指定lambda返回类型
首先给出一个例子,使用transform算法对容器内所有元素取绝对值
transform(vec.begin(),vec.end(),vec.begin(),[](int i){return i<0 ? -i : i;});
如果修改成如下格式
transform(vec.begin(),vec.end(),vec.begin(),[](int i){if(i<0) return -i else return i;});
发现编译器过不去。是因为,默认情况下,如果一个lambda体包含return之外的任何语句,则编译器假定此lambda返回void,所以我们要指定返回类型
transform(vec.begin(),vec.end(),vec.begin(),[](int i)->int{if(i<0) return -i else return i;});
(6)bind函数
使用bind函数可以解决函数参数不对应的问题,下面是使用bind重排参数顺序的实例
using namespace std::placeholders;
sort(vec.begin(),vec.end(),cmp);
sort(vec.begin(),vec.end(),bind(cmp,_2,_1)); //颠倒参数传递
使用引用传递bind
for_each(vec.begin(),vec.end(),bind(print,ref(os),_1,' '));