accumulate第三个三处所传的储值的类型必须定义了 “+”运算符,例如:将空串当作一个字面值传给第三个参数是不可以的
//会导致编译错误,const char*上并没有定义"+"运算符 string sum = accumulate(v.cbegin(), v.cend(), ""); //string上定义了"+"运算符 string sum = accumulate(v.cbegin(), v.cend(), string(""));
- 只接受一个单一迭代器来表示第二个序列的算法,都假设第二个序列至少与第一个序列一样长;
back_inserter是一种向容器中添加元素的迭代器,当我们通过此迭代器赋值时,赋值运算符会调用push_back;
vector<int> vec; //创建一个空vector fill_n(back_inserter(vec), 10, 0); //添加10个元素到vec
关于lambda表达式:
(1)表示一个可调用的代码单元,可以将其理解为一个未命名(编译器会给它命名)的内联函数;其实是一个函数对象,[ ] 称为lambda introducer,取用外部的变量要放在[ ]中;auto f = [] { std::cout << "hello lambda" << std::endl; }; f(); // prints "hello lambda"
(2)可能定义在函数内部,必须使用尾置返回,不能有默认参数,可以直接使用定义在当前函数之外的名字,例如cout;
(3)可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体;
(4)可以传值或者传引用,要修改传进来的数据必须在()后声明 mutable;被捕获的值是在创建时拷贝,而不是调用时拷贝;
(5)可以在lamada函数体内部像其他函数一样定义static变量等等;
(6)可以使用隐式捕获,但不推荐;
(7)当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名的类类型),使用auto定义一个用lambda初始化的变量时,定义了一个从lambda生成的类型的对象;
(8)lambda主要应用于原来我们传给标准库的一些函数的自定义参数时,比如sort函数,现在我们可以改用lambda表达式来自定义我们的比较函数,表达更方便;原来我们传递给标准库有些函数(比如find_if)的任何函数都只能接受一个参数,现在我们可以使用lambda来解决这个问题int id = 0; //由于是传值,内部改变不会影响外部,并且对应于(4),被捕获的值是在创建时拷贝,不是调用时拷贝 auto f = [id]()mutable { //由于使用mutable进行说明,所以可以在内部改变id的值,否则不能改变 std::cout << "id:" << id << std::endl; ++id; }; id = 42; f(); f(); f(); //id:0 id:1 id:2 /*该lambda表达式可以类似为下面的class,但还有一些差别*/ class Functor { private: int id; public: void operator() { std::cout << "id:" << id << std:endl; ++id; } }; Functor f;
- 占位符,形式为_n,n表示第几个参数;定义在名为placeholders的命名空间中,这个命名空间本身又定义在std中; using namespace std::placeholders; placeholders空间定义在functional头文件中
可以将bind函数看做一个通用的函数适配器,可以使用占位符对原函数重新包装
(1)重排参数顺序//g是是一个有两个参数的可调用对象 auto g = bind(f, a, b, _2, c, _1); //生成一个新的可调用对象g,g的第一各参数被传递给f作为最后一个参数,g的第二个参数被传递给f当做第三个参数 // 调用g(X, Y); 相当于调用 f(a, b, Y, c, X);
(2)绑定引用参数
//有些绑定的参数我们希望以引用方式传递,或者时要绑定的参数的类型无法拷贝(例如:ostream类型) // bind只会拷贝传给它的参数,如果我们希望传递给bind一个对象又不拷贝它,就必须使用标准库ref函数 for_each(words.begin(), words.end(), bind()print, ref(os), _1, ' '));
流迭代器
(1)istream_iterator// 从cin读取int,一直到eof,将输入的值用来构造vec istream_iterator<int> in_iter(cin), eof; vector<int> vec(in_iter, eof); // 也可以使用算法来操作流迭代器,计算输入的int型数字的和 cout << accumulate(in_iter, eof, 0) << endl;
(2)ostream_iterator
//使用ostream_iterator来输出值的序列,每个元素输出后还打印出一个空格(也可以是其他字符串,但必须是C风格的) ostream_iterator<int> out_iter(cout, " "); for (auto e : vec) *out_iter++ = e; //赋值语句实际上将元素写到cout cout << endl; // 运算符*和++实际上对ostream_iterator对象那个不做任何事情,但是还是推荐这种写法 //调用copy来打印vec中的元素,比循环更加简单 copy(vec.begin(), vec.end(), out_iter); cout << endl;
- 可以调用reverse_iterator的base成员来将一个反向迭代器转换成其对应的普通迭代器(即正向)
- 迭代器总共有5种,从下往上分别为继承关系
(1)input iterator;
(2)output iterator;
(3)forward iterator;
(4)bidirectional iterator;
(5)random-access iterator;
//练习10.30
istream_iterator<int> in_iter(cin), eof;
vector<int> vec(in_iter, eof);
sort(vec.begin(), vec.end());
ostream_iterator<int> out_iter(cout, " ");
copy(vec.begin(), vec.end(), out_iter);
/*消除重复单词,并统计长度大于sz的单词数量*/
#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
using namespace std;
void elimDups(vector<string> &words)
{
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
}
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
//根据ctr的数值来判断返回单词的单数还是复数形式
string make_plural(size_t ctr, const string &word,
const string &ending)
{
return (ctr > 1) ? word + ending : word;
}
void biggies(vector<string> &words,
vector<string>::size_type sz)
{
elimDups(words); //按字典序排序,删除重复单词
//按长度排序,长度相同的单词维持字典序
stable_sort(words.begin(), words.end(),
[](const string &a, const string &b)
{ return a.size() < b.size(); });
//获取一个迭代器,指向第一个满足size() >= sz 的元素
auto wc = find_if(words.begin(), words.end(),
[sz](const string &a)
{ return a.size() >= sz; });
//计算元素数目
auto count = words.end() - wc;
/*
//直接调用count_if,获得满足size()>= sz的元素个数
auto count = count_if(words.begin(), words.end(),
[sz](const string &a)
{ return a.size() >= sz; });
*/
cout << count << " " << make_plural(count, "word", "s")
<< " of length " << sz << " or longer " << endl;
for_each(wc, words.end(),
[](const string &s) { cout << s <<" "; });
cout << endl;
}
int main()
{
vector<string> words = {"the","quick","red","fox","jumps","over","the","slow","red","turtle"};
biggies(words, 5);
return 0;
}