c++primer笔记----泛型算法

  • 大多数算法在<algorithm>。泛型算法运行在迭代器之上
auto result = find(vec.begin(), vec.end(), val);
int ia = [1, 2, 3];
int * result = find(begin(ia), end(ia));
  • 数组利用指针实现泛型算法
  • 只读算法:findcountaccumulate, <numeric>里equal
  • 迭代器参数:有的算法读取两个序列进行比较或转换,只需要容器中元素可以进行就行。所以vectorlistintdouble都可以的
  • 写容器元素的算法:不做安全性检查、back_inserter可以改变容器大小,通过它赋值,就是插入、拷贝算法
vector <int> vec; 
auto it = back_inserter(vec);
*it = 42; 相当于push_back()

int a1 = {1, 2, 3};
int a2[sizeof(a1)/sizeof(*a1)];
auto ret = copy(begin(a1), end(a1), a2);  //<iterator>中的begin()
  • 重排容器元素的算法
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();
}
sort(words.begin(), words.end(), isShorter);

//如果想同等长度下,按照字典顺序
elimDups(words);
stable_sort(words.begin(), words.end(), isShorter);
  • lambda表达式:可能定义在函数的内部,必须使用尾置返回来指定返回类型。

    [comture list一般为空,是lambda所在函数中定义的局部变量的列表] (parameter list) -> return type {function body}
    。可以省略参数列表和返回类型。如果函数体包含除return之外的语句,且未指定返回类型,则是void
stable_sort(words.begin(), words.end(), [] (const string &a, const string &b)
{return a.size()<b.size()}     //长度短的在前面,返回true的在前面
  • 一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数体中使用变量
auto wc = find_if(words.begin(), words.end(), [sz](const string &a) 
{ return a.size() >= sz; } );  //返回第一个长度不小于sz的元素的迭代器
  • 捕获列表只用于局部非static变量,lambda表达式可以直接使用局部static变量和它所在函数之外的声明的变量
for_each(wc, words.end(), [] (const string &a) { cout << s << " ";});
  • 可以这样理解,向函数传递一个lambda时,同时定义了一个新类型和该类型的一个对象:传递的参数就是这个未命名的对象

  • 捕获分为值捕获和引用捕获。当使用引用方式捕获一个变量时,必须保证lambda在执行时是存在的。[a] or [&a]

  • 值捕获也可以改变捕获的值,mutable

[v1] () mutable {return ++v1};
  • 隐式捕获:[= or &]让编译器推断捕获列表
  • 混合捕获:[=, &a]默认的是值捕获,引用捕获需要显示捕获
  • 参数绑定:bind
//在<functional>
bool check_size(const string &s, string::size_type sz)
{
    return s.size() >= sz;
}
using std::placeholder::_1;
auto check6 = bind(check_size, _1, 6);  //表示check6(_1) -> check_size(_1, 6)

//bind的那些不是占位符的参数被拷贝到Bind返回的可调用对象中
//如果不能拷贝
ostream &print(ostream &os, const string &s, char c)
{
    return os << s << c;
}

bind(print, ref(os), _1, ' ');    //ref函数定义在<functional>,  cref
  • 插入迭代器:接受一个容器,生成一个迭代器,实现向给定容器添加元素
back_inserter : push_back
front_inserter : push_front
inserter : insert(it, val)
  • iostream迭代器:istream_iterator操作
istream_iterator<int> int_it(cin);  //从cin中读取Int数据
istream_iterator<int> eof;  //尾后迭代器
while (in_iter != eof)
      vec.push_back(*in_iter++);

//或者从迭代器范围构造vec,当关联的流遇到文件尾或IO错误,迭代器的值就是eof
vector<int> vec(in_iter, eof)

//使用算法操作流迭代器
cout << accumulate(in, eof, 0)
  • ostream_iterator的操作
ostream_iterator<int> out_iter(cout, " "); //在输出每个int后,输出" "
for(auto e :  vec)
    *out_iter++ = e;   //等价于 out_iter = e
cout << endl;

//或者调用copy , std::copy, <algorithm>
copy(vec.begin(), vec.end(), out_iter);
cout << endl;
  • 使用流迭代器处理类类型
istream_iterator<Sales_item> item_iter(cin), eof;    //类定义了 << 
ostream_iterator<Sales_item> out_iter(cout, "\n");  //类定义了 >>
  • 反向迭代器
vec.crbegin()  //++之后指向前一个元素

cr_test.base();   //装换为正向迭代器
  • 迭代器类别:输入迭代器,find、输出迭代器,copy and ostream_iterator、前向迭代器,replace,可进行同一个位置的多次读写、双向迭代器,list的迭代器、随机访问迭代器,array, deque, string, vector的迭代器
  • 对于每个迭代器参数来说,其能力必须与规定的最小类别相当

  • 算法命名规范

unique(beg, end);
unique(beg, end ,comp);   //使用重载形式传递一个谓词

//_if
find(beg, end, val)
find(beg, end, pred)  //返回第一个令pred为真的元素

//拷贝与不拷贝
reverse(beg, end);
reverse_copy(beg, end, dest)
  • 特定容器的算法:是list和forward_list的成员函数算法,有的操作会改变容器

猜你喜欢

转载自blog.csdn.net/qq_28038207/article/details/81269441
今日推荐