C++Primer第5版读书笔记(第10章)

第10章 泛型算法
10.3.2 lambda表达式

  1. 可调用对象:对于一个对象或一个表达式,如果可以对其使用调用运算符则称为可调用的;可调用对象主要有:函数、函数指针、重载了函数调用运算符的类和lambda表达式。
  2. lambda表达式的定义形式:
[capture list](parameter list)->return type {function body}
/**********************************
其中,capture list(捕获列表)是一个lambda所在函数中定义的局部变量的列表(通常为空);return type、parameter list和function body与任何普通函数一样,分别表示返回类型、参数列表和函数体。但是与普通函数不同,lambda必须使用尾置返回来指定返回类型。
尾置返回类型跟在形参列表后面并以一个->符号开头
***********************************/
//通常可以忽略参数列表和返回类型,但必须包含捕获列表和函数体;
auto f = [] { return 42; };
 3. 与普通函数不同,lambda不能有默认参数;
 4. 一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数中使用该变量;
[sz](const string &a)
    { return a.size() >= sz; };

10.3.3 lambda捕获和返回

  1. 值捕获:与传值参数类似,采用值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝;
  2. 引用捕获:当对象不能拷贝时,可以采用引用捕获的方式;当采用引用捕获时,必须保证在lambda执行时变量是存在的。
  3. 隐式捕获:为了指示编译器推断捕获列表,应在捕获列表中写一个&或=,&告诉编译器采用捕获引用方式;=则表示采用值捕获方式;
//sz为隐式捕获,值捕获方式
wc = find_if(words.begin(), words.end(),
            [=](const string &s){ return s.size()>=sz; });
 4. 当混合使用隐式捕获和显式捕获时,捕获列表中的第一个元素必须是一个&或=,并且显式捕获的变量必须使用与隐式捕获不同的方式;

C++Primer第5版读书笔记(第10章)_第1张图片

 5. 可变lambda:默认情况下,对于一个值被拷贝的变量,lambda不会改变其值。通过在参数列表后加上关键字mutable,可以改变一个被捕获的变量的值;
 6. 指定lambda返回类型:需要为一个lambda定义返回类型时,需使用尾置返回类型;
transform(vi.begin(), vi.end(), vi.begin(),
        [](int i)->int { if(i<0) return -i; else return i;});

10.3.4 参数绑定

  1. 标准库bind函数定义在functional头文件中:调用bind的一般形式为
auto newCallable = bind(callable, arg_list);
/*****************************
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。即,当调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,依次类推。
*****************************/
auto g = bind(func, a, b, _2, c, _1);
//传递给g的参数按位置绑定到占位符,即,第一个参数绑定到_1,第二个参数绑定到_2。
 2. 使用placeholders名字,名字_n都定义在一个名为placeholders的命名空间中,而这个命名空间本身定义在std命名空间中。
    //例如,_1对应的using声明为:
    using std::placeholders::_1;
    //或
    using namespace std::placehoders
 3. 如果希望传递给bind一个对象而又不拷贝它,需使用标准库ref函数,cref函数生成一个保存const引用的类。
for_each(word.begin(), words.end(),
        bind(print, ref(os), _1, ' '));

10.4 再探迭代器
迭代器分为:插入迭代器、流迭代器、反向迭代器和移动迭代器。
10.4.1 插入迭代器
C++Primer第5版读书笔记(第10章)_第2张图片
插入器有三种类型,差异在于元素插入的位置:

  • back_inserter创建一个使用push_back的迭代器;
  • front_inserter创建一个使用push_front的迭代器;
  • inserter创建一个使用insert的迭代器,此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。

10.4.2 iostream迭代器
C++Primer第5版读书笔记(第10章)_第3张图片
C++Primer第5版读书笔记(第10章)_第4张图片
10.5 泛型算法结构
C++Primer第5版读书笔记(第10章)_第5张图片

10.6 特定容器算法
C++Primer第5版读书笔记(第10章)_第6张图片
C++Primer第5版读书笔记(第10章)_第7张图片
C++Primer第5版读书笔记(第10章)_第8张图片

你可能感兴趣的:(C++)