泛型演算法的基礎是迭代器。
迭代器令演算法不依賴於容器,但是演算法依賴於元素型別的操作。也即:演算法永遠不會執行容器的操作。
那麼,如果想向容器中新增元素或者執行其他的一些操作呢?標準庫提供了插入迭代器來完成。但演算法自身永遠不會做這樣的操作。
唯讀演算法
1int sum = accumulate(vec.cbegin(), vec.cend(),0);2
//第三個引數型別決定了函式中使用哪個加法運算子及返回值型別
這裡面蘊含著乙個程式設計假定:將元素型別加到和的型別上的操作是可行的。
1string sum = accumulate(v.cbegin(), v.cend(), string(""
));2
//錯誤:string無法轉換為const char*
3string sum = accumulate(v.cbegin(), v.cend(), "");
best practice:對於唯讀演算法,最好使用cbegin()和cend()。
寫演算法
演算法不會執行檢查操作,不會檢查寫演算法。
重排容器的演算法
1//消除重複單詞
2void elimdups(vector &words)
3
謂詞是乙個可呼叫表示式,其返回乙個能用作條件的值。到目前為止,我們僅用過兩種可呼叫物件:函式和函式指標。還有其他兩種可呼叫物件:過載了函式呼叫運算子的類和lambda表示式。
lambda表示式:
具有乙個返回型別、乙個引數列表、乙個函式體。
1 [capture list] (parameter list) -> return type
表示式格式說明:
「我們可以忽略引數列表和返回型別,但必須永遠包含捕獲列表和函式體。
忽略引數列表,等價於乙個空引數列表;忽略返回型別,如果函式體只有乙個return語句,則從返回的表示式推斷函式型別,否則,返回型別為void。
雖然乙個lambda可以出現在乙個函式中,使用其區域性變數,但它只能使用那些明確指明的變數。
乙個lambda可以直接使用定義在當前函式之外的名字。即:捕獲列表只用於區域性非static變數,lambda可以直接使用區域性static變數和在它所在函式之外宣告的名字。」
1void biggies(vector &words, vector::size_type sz)2);
6//獲取第乙個size大於sz的元素
7 auto wc = find_if(words.begin(), words.end(), [sz](const
string &a) );8//
size大於sz的元素數目
9 auto count = words.end() -wc;
10 cout <11//
列印這些單詞
12 for_each(wc, words.end(), (const
string &s) );
13 cout <14 }
當定義乙個lambda時,編譯器生成乙個與lambda對應的新的(未命名的)類型別。當向乙個函式傳遞乙個lambda時,同時定義了乙個新型別和該型別的乙個物件:傳遞的引數就是此未命名物件。
捕獲分為值捕獲和引用捕獲:
**獲的變數的值是在lambda建立時拷貝,而不是呼叫時拷貝;
如果lambda可能在函式結束後執行,捕獲的引用指向的區域性變數已經消失;
確保lambda每次執行的時候,資訊都有預期的意義,是程式設計師的責任;一般來說,我們應該儘量減少捕獲的資料量,來避免潛在的捕獲導致的問題,而且,如果可能的話,應該避免捕獲指標和引用。
捕獲分為隱式捕獲和顯式捕獲。
如果混合使用隱式捕獲和顯式捕獲,顯式捕獲必須使用與隱式捕獲不同的方式:如果隱式捕獲使用引用方式(&),則顯示捕獲使用值方式;反之亦然。
可變lambda:
如果我們希望能改變乙個**獲的變數的值,就必須在引數列表首加上關鍵字mutable。
對於那種只在一兩個地方使用的簡單操作,lambda表示式是最有用的;如果我們需要在很多地方使用相同的操作,通常應該定義乙個函式,而不是多次編寫相同的lambda表示式。
如果lambda的捕獲列表為空,可以用函式來替代它。但是,對於捕獲區域性變數的lambda,用函式來替換它就不是那麼容易了。我們必須解決這一問題。
1 auto newcallable = bind(callable, arg_list);
1bool check_size(const
string &s, string
::size_type sz)25
6 auto check6 = bind(check_size, placeholders::_1, 6);
以check6為例:只有乙個佔位符:表示check6只接受乙個引數。佔位符出現在arg_list的第乙個位置,表示check6此引數對應到check_size的第乙個引數。
最後乙個問題:
1 for_each(words.begin(), words.end(), bind(print, os, _1, ''));//
錯誤,os不能拷貝
2 for_each(words.begin(), words.end(), bind(print, ref(os), _1, '
'));
其他迭代器:流迭代器、插入迭代器、反向迭代器、移動迭代器。
演算法形參的4種模式:
1alg(beg, end, other args);
2alg(beg, end, dest, other args);
3alg(beg, end, beg2, other args);
4 alg(beg, end, beg2, end2, other args);
list和forward_list使用自己的演算法會比較好。
chapter10使用Using機制
使用using機制 1.操作硬碟,就需要try.catch 2.為了簡化try.catch的機制,使用using 3.凡是使用了using 自動釋放資源的地方,必須實現idisposable介面 源 使用using自動釋放資源,不用再寫fs.close using system using syst...
chapter 10 迴圈網路架構
語言模型是rnn常關注的乙個問題,我們希望能讓演算法能夠在我們給出乙個首字元的情況下,給出後面的字元的 在我看來,這不僅可以用於搜尋引擎,在考慮了語境後,或許也可以用來寫文章或繪畫。以下是rnn的幾個例項 我們可以使用莎士比亞的文集來訓練演算法,來得到習得了莎翁文風的演算法。將一大堆代數托補學教材的...
Chapter10 模板方法模式
模板方法模式,定義乙個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變乙個演算法的結構即重定義該演算法的某些特定步驟。父類可以成為子類的模板,所有重複的 都應該要上公升到父類去,而不是讓每個子類都去重複。當我們要完成某一細節層次一致的乙個過程或一系列步驟,但其個別步驟在更詳...