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