vector有一些操縱大小的操作,capacity()列印現在的大小,reserve(n)保持儲存n個元素,shrink_to_fit()將capacity恢復到現在
容器的大小。reserve並不會減少空間或代替resize的能力。看來這種相當的簡單。
跳過下面有關string的部分。
容器介面卡,是基於一些順序容器構造的資料結構,這些資料結構要根據基本的底層容器進行初始化。(利用已初始化的命名物件進行初始化)
但對介面卡本身進行改變後,並不能對相應的底層容器進行相應的訪問操作,特別地,底層容器的size等並沒有改變。
這僅僅是用來初始化,(而且不能對有元素的底層容器進行初始化)而非實際儲存。
棧stack提供4種操作,push pop emplace top(對應於類vector的 front end)
queue僅僅是具備先進先出的特性,priority queue具備按優先順序進行排序的特點。(進出特性明確)
queue可以用vector作為底層容器實現的原因可能在於erase方法。關於優先佇列介面卡的部分且不述,編譯器並未支援。
下面展開有關泛型演算法的討論。
泛型演算法的設定是對迭代器範圍內的元素進行處理。
find:查詢指定元素,並返回指定元素的迭代器,如沒有,返回第二個迭代器(「尾後」迭代器)。
由於其嚴謹的泛型形式導致其不能在string中對子string進行查詢。
將find函式應用於指標範圍也是可以的,一般指標由begin end 函式(不需要載入庫)得到。
泛型演算法一般和序有關的操作應當依賴於容器類中的"==",但相應的操作可以通過指定謂詞來進行(不需要過載操作符)。
其進行的操作可以視為迭代進行,並不改變容器大小,這可以從algorithm remove中看到。
想利用remove刪除元素,可以利用remove返回移動後原迭代範圍的尾後迭代器,結合erase範圍刪除得解。
numeric accumudate演算法將範圍元素進行「累加」,並將第三個引數作為初值傳入。(這裡存在允許型別轉換的假定)
algorithm equal由於相同容器例項化型別封裝了"==",equal主要用來在不同容器間進行比較,接受乙個迭代範圍及另乙個範圍
的起始迭代器。對於封裝比較operator的說明,以自定義的過載運算為準。
algorithm fill向乙個容器範圍寫入給定的元素(第三個引數)
fill_n接受三個引數,寫入的起始迭代器,寫入元素的數量,寫入的值。(可以將某容器元素都設定為某值)
容器庫泛型演算法,並不能對容器大小進行改變,與之相對的,iterator庫中提供了可以插入容器元素的迭代器,
但在容器操作上並沒有什麼實質上的不同。僅僅是提供了不同的介面。
以iterator::back_inserter為例,利用其對某一容器進行初始化,返回乙個可以執行尾部插入的迭代器,但其內部仍然呼叫
push_back方法。(只有能執行相關操作的容器才能這樣做)
如果是單純地使用iterator的上述相應所謂迭代器介面卡,其結果與基本操作無異,但是將其作為泛型演算法迭代器範圍的引數,
能起到加成的作用,比如將上述back_inserter應用於fill_n 即可實現不已迭代為形式的擴張插入。
標準庫begin end函式被定義在標頭檔案iterator中,被用來返回迭代器。
對拷貝演算法,其常常與back_inserter相配合使用。這裡對back_inserter的看法是相對模糊的,但能夠理解。
對於容器中元素進行改變的演算法,一般有兩個版本,一種是改變原容器,另一種是得到乙個拷貝(原容器不變)
以replace為例,replace接受4個引數,前兩個是迭代器範圍,後兩個是將某值替換為其它值。這是乙個該變原容器的演算法,
不改變的版本為replace_copy,其接受第三個引數(共5個引數)為將改變後的版本插入的位置。
對容器元素的重排(元素過載序運算)刪除多呼叫標準庫algorithm::sort 及 unique,後者返回第乙個不滿足唯一性的迭代器,
之後使用erase即可。sort具有可選的第三個引數作為排序的謂詞(bool型別函式指定序)。
在自定義謂詞進行排序時,涉及乙個問題,即是新序對舊序的完全替換還是,在舊序上發展而來,
在這裡,有stable_sort方法實現在首先滿足新序的情況下,利用舊序對新序下相等的元素進一步排(即序的優先順序問題)
標準庫algorithm::find_if 對乙個迭代器範圍尋找第乙個符合第三個引數(謂詞)的迭代器。(否則返回尾後)
lambda表示式,的注意事項:lambda表示式必須包含捕獲引數列表(可以是空列表),其它部分在理論上是可以省略的。
當lambda函式體僅由乙個return語句組成時。(此時與python中的lambda表示式是等價的),省略的返回值
型別可以由編譯器推斷獲得。(可省略)
但當lambda函式體中除了return還有其它語句時,如果省略返回值型別,會將返回值型別置為void,應當保持返回
值型別的寫作。(雖然實現由編譯器實現可能導致對的情況)
auto f = [capture list](para list)-> return_type; (注意 ; 的安排)
由於演算法所指定接收的謂詞一般僅對容器中的元素提供介面,當想要動態地將與處理結果有關的引數傳入謂詞時問題有一些麻煩,
這在指令碼語言中是容易的(在python中,其轉化為對函式提供預設引數或動態地指定某引數值的問題,利用functools.partial
可以很好地解決),但在c++中就需要利用閉包的概念。
程式設計中閉包的一大特性是可以將閉包置於另乙個環境(函式環境)中,並使用該環境中的變數(如python函式巢狀定義),
實際在數學中就相當於對乙個空間指定子空間,子空間具有空間的全部性質,可見python所定義的函式空間「太好了」。
這與數學中的閉包特性是基本吻合的。對於距離空間的乙個子集,可以得到這個子集的閉包,在閉包中進行cauchy收斂,
所收斂的點都在此閉包中,閉包是自治的。由於要求閉包的這種自治性,對於大多數支援變數即是物件的指令碼語言,閉包會有較好的支援。
lambda表示式:
基本具備形式 [capture list](parameter list) -> return type
一般返回引數形式可以由function body推得,故最簡形式為:
(parameter list)
注意:這裡有時捕獲列表沒有捕獲變數,但也需要給出空列表。
宣告lambda表示式這一可呼叫物件,一般儲存此部分時要宣告相應的型別,
最為簡單的方法是將其賦給auto進行自動型別推斷,
顯式宣告也是可以的,採用functional庫中的function模板對返回值及引數
組成的元素進行例項化即可。
如:functionb = (const int&i);
就是儲存可呼叫物件的一種方法。
對lambda表示式中捕獲引數列表中的引數一般可以有兩種操作,即改變與不改變
兩種。進行改變操作時,應將其宣告為引用。否則對非引用形式的捕獲引數變數
在lambda函式體中進行改變會被視為非法的。(直接編譯出錯,提示read only
valuable)
lambda表示式實現了閉包的概念,一般地如上初始化乙個lambda表示式是採用
只閉不包的形式,即限定表示式的變數環境。
但也可以在捕獲列表中使用= 或 & 將所有外包的環境變數包含在內部體中。
對於上面的值捕獲及引用捕獲方式,也可以採用混合的方法,即在捕獲列表中
既宣告全體的值捕獲,又宣告個體的引用捕獲。
由於c++的編譯特性,導致在lambda表示式捕獲列表宣告時,要求捕獲的表示式在之前
宣告時必須是已定義的,並且在宣告後對此變數進行改變不會改變在編譯期已經
決定的捕獲變數值,這與python等動態型別語言是不同的。
當然這是值拷貝的情況:
ex:
size_t v1 = 42;
auto f = [v1]()mutable;
v1 = 0;
auto i = f();
cout << i ); cout << endl;
}
一些如插入迭代器之類的back_inserter(back_insert_iterator) inserter等顯式宣告其型別是比較麻煩的,
可用auto宣告型別。
重拾C 教程 環境
在這一章中,我們將討論建立 c 程式設計所需的工具。我們已經提到 c 是 net 框架的一部分,且用於編寫 net 應用程式。因此,在討論執行 c 程式的可用工具之前,讓我們先了解一下 c 與 net 框架之間的關係。net 框架是乙個創新的平台,能幫您編寫出下面型別的應用程式 net 框架應用程式...
重拾C 教程 封裝
封裝被定義為 把乙個或多個專案封閉在乙個物理的或者邏輯的包中 在物件導向程式設計方 中,封裝是為了防止對實現細節的訪問。抽象和封裝是物件導向程式設計的相關特性。抽象允許相關資訊視覺化,封裝則使開發者實現所需級別的抽象。c 封裝根據具體的需要,設定使用者的訪問許可權,並通過訪問修飾符來實現。乙個訪問修...
重拾C 教程 列舉
列舉是一組命名整型常量。列舉型別是使用enum關鍵字宣告的。c 列舉是值型別。換句話說,列舉包含自己的值,且不能繼承或傳遞繼承。宣告列舉的一般語法 enum 其中,列舉列表中的每個符號代表乙個整數值,乙個比它前面的符號大的整數值。預設情況下,第乙個列舉符號的值是 0.例如 enum days 下面的...