1. 程式人生 > >10.3 Customizing Operations(自定義操作)

10.3 Customizing Operations(自定義操作)

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;
}