10.3 Customizing Operations(自定义操作)

时间:2021-06-05 03:00:46

10.3.2 Lambda Expression(匿名函数)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>

using namespace std;

bool isShorter(const string &s1, const string &s2) {
    return s1.size() < s2.size();
}

void elimDups(vector<string> &word) {
    stable_sort(word.begin(), word.end(), isShorter);
    //字符大小从小到大排序
    auto end_unique = unique(word.begin(), word.end());
    word.erase(end_unique, word.end());
}

int main()
{
    vector<string> vec = { "hello", "ni", "aui", "ni", "wup", "hello", "ni" };

    elimDups(vec);

    for (auto &i : vec) {
        cout << i << " ";
    }

    system("PAUSE");
    return 0;
}

 

 Like find the find_if algorithm takes a pair of iterators denoting a rang.Unlike the find ,the third argument to  find_if is a predicate.The find_if  algorithm calls the given predicate on each element in the input range.It returns the first element for which the predicate returns a nonzero vaule, or its end iterator if no such element is found.

[capture list](parameter list) -> return type { function body }

  

我们能够省略形参列表和返回类型之一或者全部,但必须包含获取列表和函数主体。

#include <iostream>
#include <algorithm>

using std::cout;
using std::endl;

int main()
{
    auto f = [] { return 66; };

    cout << f() << endl;

    system("PAUSE");
    return 0;
}

在一个匿名函数中,省略圆括号和参数列表,等同于指定一个空参列表。

改编开头的例子:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>

using namespace std;

void elimDups(vector<string> &word) {
    stable_sort(word.begin(), word.end(), [](const string &s1,
        const string &s2)-> bool{ return s1.size() < s2.size(); });
    //字符大小从小到大排序
    auto end_unique = unique(word.begin(), word.end());
    word.erase(end_unique, word.end());
}

int main()
{
    vector<string> vec = { "hello", "ni", "biu", "ni", "qiu", "hello", "ni" };

    elimDups(vec);

    for (auto &i : vec) {
        cout << i << " ";
    }
    cout << endl;

    system("PAUSE");
    return 0;
}

 

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>

using namespace std;

void elimDups(vector<string> &word, int sz) {
    stable_sort(word.begin(), word.end(), [](const string &s1,
        const string &s2)-> bool{ return s1.size() < s2.size(); });
    //字符大小从小到大排序
    auto end_unique = unique(word.begin(), word.end());
    word.erase(end_unique, word.end());
    auto wc = find_if(word.begin(), word.end(), [sz](const string &a)
     -> bool{ return a.size() >= sz; });
    //->bool可以不写,计算机能够通过a.size() >= sz;判断出返回类型
    //find_if返回第一个满足条件元素的迭代器
    //如果没有满足条件的,复制word.end()给wc

    if (wc == word.end()) {
        cout << "no bigger of " << sz << endl;
        return;
    }

    for (auto i = wc; i < word.end();) {
        cout << *i++ << endl;
    }
}

int main()
{
    vector<string> vec = { "hello", "ni", "biu", "ni", "qiu", "hello", "ni" };

    elimDups(vec, 3);

    system("PAUSE");
    return 0;
}

 

10.3.3 匿名函数列表获取和返回

当我们定义一个匿名函数时,编译器生成对应匿名函数列表的一个新的(未命名)类型。类似于普通函数,但是未命名。

 

我们能够通过值获取或者引用获取参数列表。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    int a = 9;
    auto val = [a](int b = 5) { return a + b; };
    //值传递
    cout << val() << endl;

    //auto val1 = [&a](int b = 5) { return ++a; };
    //cout << val1() << endl;
    auto val2 = [&a](int b = 5) {return a + b; };
    //引用传递
    cout << val2() << endl;
    a += 2;
    cout << endl;

    cout << "值传递再次调用结果:" << val() << endl;
    cout << "引用传递再次调用结果:" << val2() << endl;


    system("PAUSE");
    return 0;
}

当我们通过引用获取值时,我们必须确定这个值在匿名函数执行时存在。

 

如果可能的话,避免使用指针或者引用获取值。

 

&告诉编译器通过引用获取值,=告诉编译器通过值获取值。

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

void biggist(vector<string> &words, vector<string>::size_type sz, ostream &os = cout, char c = ' ') {
    auto po = find_if(words.begin(), words.end(), [=](const string &s) {return s.size() >= sz; });
    //sz值获取
    cout << "size over or equipment 3:" << *po << endl;

    for_each(words.begin(), words.end(), [&, c](const string &s) { os << s << c; });
    //os引用获取,c值获取
    cout << endl;

    for_each(words.begin(), words.end(), [=, &os](const string &s) {os << s << c; });
    //os引用获取,c值获取
}

int main()
{
    vector<string> vec = { "heoo", "hi", "biu", "cps", "heiuwe" };
    vector<string>::size_type n = 3;

    biggist(vec, n);

    system("PAUSE");
    return 0;
}

 

 

transform算法和一个匿名函数用绝对值代替一个顺序函数中的负值。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    vector<int> vec = { -1, 2, 3, -4, 5, 6 };

    transform(vec.begin(), vec.end(), vec.begin(), [](int i) {return i < 0 ? -i : i; });
    //编译能够通过i < 0?判断返回类型
    transform(vec.begin(), vec.end(), vec.begin(), [](int i) { if (i < 0) return -i; else return i; });
    //按照C++11标准,这样写error,无法通过i或者-i判断返回类型,但是编译器自身优化了,可以输出
    transform(vec.begin(), vec.end(), vec.begin(), [](int i) -> int{ if (i < 0) return -i; else return i; });
    //第二种的标准写法
    system("PAUSE");
    return 0;
}

 

 

10.3.4 绑定实参

auto newCallable = bind(callable, arg_list);

bind()在头文件<functional>中

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;
using namespace std::placeholders;

bool check_size(const string &a, string::size_type sz) {
    return a.size() >= sz;
}

int main()
{
    auto check = bind(check_size, _1, 5);
    //_1所在位置表示函数参数列表第几位参数待输入,1表示check()时传入的第一个值
    string s = "hello";

    bool n = check(s);

    cout << n << endl;

    system("PAUSE");
    return 0;
}

 

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <string>

using namespace std;
using namespace std::placeholders;

void func(const string &a, const string &b, const string &c, const string &d) {
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "c:" << c << endl;
    cout << "d:" << d << endl;
}

int main()
{
    auto f = bind(func, "hello", _2, "liu", _1);
    //_2所在位置,表示第二个函数参数,2表示第二个获取值。
    //_2所在位置,表示第四个函数参数,1表示第一个获取值。
    f("ran", "ya");
    //"ran"给_1, "ya"给_2

    system("PAUSE");
    return 0;
}

 

 

因为ostream不能被copy,但我们能够使用ref函数返回一个对象的引用,引用对象的可以被copy的

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <string>

using namespace std;
using namespace std::placeholders;

ostream &print(ostream &os, const string &s, char c) {
    
    return os << s << c;
    //s和c的数据流传送到os中,再return,os输出对象是屏幕
}

int main()
{
    ostream &os = cout;
    vector<string> vec = { "hello", "ni", "hao" };
    //error:for_each(vec.begin(), vec.end(), bind(print, os, _1, ' '));
    for_each(vec.begin(), vec.end(), bind(print, ref(os), _1, ' '));

    system("PAUSE");
    return 0;
}