C++之泛型算法

只讀算法

(1)accumulate返回容器的和

int sum = accumulate(vec.cbegin(),vec.cend(),0);
string sum = accumulate(v.cbegin(),v.cend(),string(""));//注意第三個參數不接受"",因爲const char*類型沒有重載“+”會編譯錯誤

(2)equal比較兩個等長的容器(元素個數相同)是否保存相同的值

equal(vec1.cbegin(),vec1.cend(),vec2.cbegin());

寫容器元素算法

(1)fill填充元素值

fill(vec.begin(),vec.end(),0);

(2)back_inserter接收一個容器的引用,返回該容器的插入迭代器,可以做插入容器操作

vector<int> vec;
auto it = back_inserter(vec);
*it = 42;  //vec中有42

vector<int> vec;
fill_n(back_inserter(vec),10,0); //添加10個元素到vec

(2)copy複製數組

int a1[] = {0,1,2,3,4,5,6};
int a2[sizeof(a1)/sizeof(*a1)];
auto ret = copy(begin(a1),end(a1),a2);

(3)replace將容器內指定值置換成另一個值

replace(vec.begin(),vec.end(),0,42);  //0換成42;

(4)replace_copy如果不想改變原數組可以使用這個,得到置換後的新數組

vector<int> newvec;
replace_copy(vec.begin(),vec.end(),back_inserter(newvec).0,42);

消除重複單詞算法

void elimDups(vector<string>& words)
{
	sort(words.begin(),words.end());
	auto end_unique = unique(words.begin(),words.end());
	words.erase(end_unique,words.end());
}

lambda表達式

(1)標準寫法
[capture list](parameter list) -> return type { function body}
我們可以忽略參數列表和返回類型,但是永遠包含捕獲列表和函數體

vector<int> vec;
sort(words.begin(),words.end(),[](const string& a,const string& b){return a.size()<b.size();}}

(2)捕獲列表
捕獲列表中的參數捕獲該函數所在的局部變量,然後在lambda表達式中可以直接進行使用,而參數列表是外部調用的時候傳入的參數。

//獲取一個迭代器,指向第一個滿足size()>=sz的元素
auto wc = find_if(words.begin(),words.end(),[sz](const string& a){return a.size() >= sz}};
//打印長度大於等於給定值的單詞,每個單詞後面接一個空格
for_each(wc,words.end(),[&os](const string& s){cout<<s<<"";});

(3)隱式捕獲和顯示捕獲
當我們混合喜歡使用隱式捕獲和顯示捕獲時,顯示捕獲的變量必須使用與隱式捕獲不同的方式。即,如果隱式捕獲是引用方式,則顯示捕獲命名變量必須採用值方式,因此不能在其名字前使用&。類似的,如果隱式捕獲採用的是值方式,則顯示捕獲命名變量必須。
(4)可變mutable
默認情況下,對應一個值被拷貝的變量,lambda不會改變其值。如果我們希望能改變一個被捕獲的變量的值,就必須在參數列表首加上關鍵字mutable。因此,可變lambda能省略參數列表:

void fcn3()
{
	size_t v1 = 42;
	auto f = [v1]()mutable{ return ++v1};
	v1 = 0;
	auto j = f();  //j = 43;
}

(5)指定lambda返回類型
首先給出一個例子,使用transform算法對容器內所有元素取絕對值

transform(vec.begin(),vec.end(),vec.begin(),[](int i){return i<0 ? -i : i;});

如果修改成如下格式

transform(vec.begin(),vec.end(),vec.begin(),[](int i){if(i<0) return -i else return i;});

發現編譯器過不去。是因爲,默認情況下,如果一個lambda體包含return之外的任何語句,則編譯器假定此lambda返回void,所以我們要指定返回類型

transform(vec.begin(),vec.end(),vec.begin(),[](int i)->int{if(i<0) return -i else return i;});

(6)bind函數
使用bind函數可以解決函數參數不對應的問題,下面是使用bind重排參數順序的實例

using namespace std::placeholders;
sort(vec.begin(),vec.end(),cmp);
sort(vec.begin(),vec.end(),bind(cmp,_2,_1));  //顛倒參數傳遞

使用引用傳遞bind

for_each(vec.begin(),vec.end(),bind(print,ref(os),_1,' '));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章