C++ STL標準程序庫開發指南學習筆記

一、類模板簡介:

? ? ? ? 在現今的C++標準模板庫中,幾乎所有的東西都被設計為template形式,不支持模板,就無法使用標準程序庫。模板庫可以認為是針對一個或多個尚未明確的類型而編寫一套函數或類型。模板是C++的一個新特性。通過使用模板,C++允許推遲對某些類型的選擇,直到想使用模板或者對模板進行專門化處理時,使用模板,可以讓程序員面對相似而又略有不同特性時,更快捷地編寫代碼,提高開發效率。

? ? ? ? C++模板功能思想:

? ? ? ? 泛型編程完美思路:

? ? ? ? 設想能否研制一種編程機制,讓一個函數適應所有的數據類型,包括自己定義的。實現這種機制,既然適應所有的數據類型,稱為泛型編程(Generic Programming)。

? ? ? ? ? ? ?泛型編程最初提出時的動機很簡單直接,就是發明一種語言機制,能夠實現:

  • ?一個通用的標準容器庫。所謂通用的標準容器庫,就是要能夠做到,如一個list類存放所有可能類型的對象;
  • 泛型編程讓編寫完全一般化并可以重復使用的算法,其效率與針對某特定數據類型而設計的算法相同。泛型即是指具有在多種數據類型上皆可操作的含義,這樣算法與數據結構完全分離。其中算法是泛型的,不與任何特定數據結構或對象類型聯系在一起。

? ? ? ? 泛型編程的代表作品STL是一種高效、泛型、可交互操作的軟件組件。STL以迭代器(iterators)和容器(containers)為基礎,是一種泛型算法(generic algoritms)庫,容器的存在這些算法又東西可操作。STL包含各種泛型算法(algoritms) 、泛型迭代(iterator)、泛型容器(containers)以及函數對象(function objects)。STL并非只是一些有用組件的集合,它是描述軟件組件抽象需求條件的一個正規而有條理的架構。

? ? ? ? 泛型的第一好處是編譯時的嚴格類型檢查。這是集合框架最重要的一個特點。此為,泛型消除了絕大多數的類型轉換。如沒有泛型,當使用集合框架時,不得不進行類型轉換。

? ? ? ? 以上概括為:它是把數據類型(包括自己定義的class類型)作為一種參數傳遞進來的機制。

? ? ? ? C++模板:

? ? ? ? 讓程序更加智能,C++很需要泛型這種新的編程模式,于是引用了模板這個功能。也就是說在C++中,引入了關鍵template。

? ? ? ? 使用模板是為了實現泛型,可以減輕編程的工作量,增加函數的重用性。注意重用性幾乎是編程的基本思路,不然也不會發明函數這種功能了。

? ? ? ? C++STL的淵源:

? ? ? ? 有了泛型編程思想,有了模板功能,C++程序員就可以編寫出很多通用的針對不同數據類型的算法,其中,STL脫穎而出,稱為C++標準,只需掌握這個標準,就不用自己費心費力從頭編寫一些算法。這就是所謂的開發基本思想:不要重復發明輪子。

? ? ? ? 簡單的說,STL(Standard Template Libarary)標準模板庫,是一個具有高可用性的、高效的C++程序庫。該庫包含了諸多在計算機科學領域里所常用的基本數據結構和基本算法,為廣大C++程序員提供了一個可擴展的應用框架,高度體現了軟件的可復用性。剛開始可以理解為C++內置的函數庫、類算法框架庫等。

? ? ? ? C++基本概念通覽:

  • 命名空間:name space是指標識符的可見范圍或者有效范圍。定義命名空間的目的是防止出現名稱沖突現象。命名空間是C++中一項較新的特性。為了將多個程序員開發(或廠商)開發的代碼便捷、高效地組合起來,防止重復的函數名、類名等,命名空間可將不同的代碼封裝在有效的范圍內;
  • 頭文件:頭文件的功能主要是將原程序片段收集到一起,形成一個提供給編譯程序的文件,一般情況下,頭文件中只包含各種聲明、常量定義、預編譯、注釋、類型定義、模板定義等。常規的函數定義、數據定義、導出的模板定義等不應該出現在頭文件中。
  • 面向對象的程序設計:面向對象時C/C++語言解決問題的一種方法。原來的程序開發是面向過程的。面向過程的程序設計主要考慮解決問題的先后順序、措施安排等,具有典型的過程性。而面向對象的程序設計主要是建立在各種對象基礎的軟件開發,每一個具有獨立特性和相應功能的個體均可以作為一個對象加以處理。
  • C++中的聲明和定義:在程序開發領域,聲明是指當一個計算機程序需要調用內存空間時,對內存發出的“占位”指令;定義是指聲明的變量、函數、類等呈現或描述出來,為其提供一個意義相當的表達,并表明其與眾不同之處,最終目的是顯示其內涵。
  • 指針:指針是C語言中一個重要概念,也是C語言的重要特色。C++沿襲了C語言的這一特色。正確而靈活地使用指針,可以有效地表示復雜的數據結構、動態分配內存、便捷地使用字符串、方便地使用數組、直接處理內存、函數可以返回多個數值等;在內存中,變量存儲在特定的地址,通過地址可以找到所需的變量,變量在內存中的地址“指向”該變量單元。一個變量的地址稱為該變量的“指針”。如有一個變量用來存儲另一個變量的地址,則稱它為“指針變量”;在學習過程中,要注意區分指針和指針變量。指針指的是該變量在內存中的存儲地址;而指針變量指的是該變量的值是一個指向其他變量的指針值。
  • 函數:C/C++程序至少需要一個main()函數。程序往往由多個函數組成。函數是C++源程序的基本模塊,通過調用相應的函數,可以實現特定的功能。C/C++語言提供了強大的、極為豐富的庫函數。另外,用戶或程序開發者可以把自己的思想或算法編寫成一個相對獨立的函數模塊。
  • 函數中變量:局部變量和全局變量;變量的存儲類別,在使用函數時涉及不同的存儲方分為靜態存儲方式和動態存儲方式;全局變量使用靜態存儲方式;函數的形參和普通局部變量使用動態存儲方式:
    1. auto類型是默認類型,可以省略不寫;
    2. static類型屬于靜態存儲類型,當希望函數中的局部變量的值在函數調用結束后不消失而保留原值時,可用關鍵字static聲明該局部變量;
    3. C語言中將局部變量的值放在CPU中的寄存器中,這種變量稱為“寄存器變量”,用關鍵字register作聲明;
    4. 如外部變量不存在文件的開頭定義,其有效的作用范圍只限于定義到文件末尾。函數需要引用該外部變量,則應該在引用之前用關鍵字extern對該變量作“外部聲明”,表示該變量是一個已經定義外部變量。有了次“聲明”起,合法地使用該外部變量。
  • 文件:C/C++中的文件一般是指,存儲在外部介質上數據的集合,并且是一組相關數據的有序集合。當文件被使用時,將其調入內存中。文件可分為兩種:一種是駐留在磁盤或其他外部介質的一個有序數據集,可以是數據文件、可執行程序;另一種是設備文件,是指和主機相聯的各種設備,像顯示器、鍵盤、打印機等;外部設備一般可以看作一個文件來進行管理,它們的輸入、輸出等同于對磁盤文件的讀和寫。
  • 程序的編譯和鏈接:
    1. 程序編譯:是指將編輯好的源文件翻譯成二進制目標代碼的過程,編譯過程時使用C語言提供的編譯程序完成的,不同操作系統下的各種編譯器的使用命令不完全相同,使用時應注意計算機環境。編譯時,編譯器首先要對源程序中的每一個語句檢查語法錯誤。當發現錯誤后,會提示錯誤的位置和錯誤類型的信息。要再次調用編輯器進行查錯修改,之后再編譯,直到排除所有語法和語義錯誤。正確的源程序文件經過編譯后在磁盤上生成目標文件
    2. 程序的鏈接:編譯后產生的目標文件是可重定位的程序模塊,不能直接運行。鏈接程序是把目標文件和其他分別進行編譯生成的目標程序木塊及系統提供的標準庫函數鏈接在一起,生成可運行的可執行文件的過程。
  • 程序的啟動和終止:對于任何一個C/C++程序,程序執行時總是從main()函數開始,之后一次或者順序執行main()函數中的程序代碼,實現其中其他函數的各種功能。
  • 異常處理:異常處理機制可看作是編譯時的類型檢查和歧義性控制機制在運行中的對應物。

? ? ? ? 類模板定義:

  • 模板庫(STL):STL另一個重要特性是它不是面向對象的。STL主要依賴于模板。這使得STL的組件具有廣泛通用性和底層特性。由于STL是基于模板的,內聯函數的使用使得生成的代碼短小高效。
  • 類模版實例化:類模版僅僅是模板,如何使用模板就涉及類模板的實例化問題。模板實例化一般指使用模板類和模板參數生成一個類聲明的過程。
  • 類模板的成員函數:可被類模板實例化產生的類所擁有。每個類模板都擁有自己相應的成員函數,這些函數可被模板的實例調用。
  • 類模板的靜態數據成員:被static修飾,意味著它為該類的所有實例所共享,即當某個類的實力修改了改靜態成員變量,其修改值為該類的其他所有實例所見。

? ? ? ? 成員模板:

? ? ? ? 一個模板可以在一個類或類模版中聲明,這樣的類模版稱為成員模版;成員模版的定義既可以在類(或類模版)定義內部,也可以在類(類模版)定義的外部;當類模版的成員模板在類模版定義的外部定義時,應該完整地指出類模版的參數和成員模版的參數。

? ? ? ??友元模版:

  • 非模版函數、類作為實例的友元;
  • 模版函數、模版類作為同類型實例類的友元;
  • 模版函數、類作為不同類型實例類的友元。

? ? ? ? 函數模版:

? ? ? ? 函數模版定義一個無限的相關函數集合。當函數除了數據類型不一致外,其余的處理全部相同,此時函數模版隨之誕生,這也是創建函數模版的原因;

? ? ? ? 函數模版可以定義參數化的非成員函數,能夠不同類型的參數調用相同的函數,由編譯器決定該采用哪種類型,從模板函數中生成相應的代碼。

? ? ? ? 類模版的參數:

? ? ? ? 模版的參數可以是類型參數,也可以由常規類型的參數。并且一個模板可有多個參數。

? ? ? ? 模板庫簡介:

? ? ? ? STL的代碼從廣義上講分為三類:algorithm(算法)、container(容器)和iterator(迭代器),幾乎所有的代碼都采用模板類和模板函數的方式,在C++標準中,STL被組織為13個頭文件:<algorithm>、<deque>、<functional>、<iterator>、<verctor>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>。

? ? ? ? STL的組件:

? ? ? ? STL是C++標準程序庫的核心。STL內所有組件都由模板構成,其元素可以是任意型別。程序通過選用恰當的群集類別,調用其成員函數和算法數據,就萬事大吉了,代價是STL并不好理解。

  • 容器:用來管理某類對象的集合;

????????

  • 迭代器:用來在一個對象群集的元素上進行遍歷動作。對象集可能是容器,也可能是容器的一部分。迭代器的主要用途是為容器提供了一組很小的公共接口,利用這個接口,某項操作可以行進至群集內的下一個元素。每種容器都提供了各自的迭代器,迭代器了解該容器的內部結構,所以能夠正確行進。迭代器的接口和一般指針差不多;
  • 算法:用來處理群集內的元素。可以出于不同目的的搜尋、排序、修改、使用那些元素。所有容器的迭代器都提供一致的接口,通過迭代器的協助,算法程序可以用于容器。
  • 仿函數:可以理解為函數的一般形式。仿函數有幾種不同的約束,對于編程來說,仿函數非常重要。
  • 內存配置器:配接器可以實現不同類之間的數據轉換。? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

二、C++中的字符串:

? ? ? ? C++標準程序庫中的字符串處理類string,在最初的C語言中,頭文件string.h提供了一系列字符串函數,早期的C++為處理字符串提供了各自的類,string類由頭文件<string>支持,該類包含了大量方法,并且包括了若干構造函數,用于字符串賦給變量、合并字符串、比較字符串和訪問各個元素的重載操作符、查找字符和子字符串的方法等。

? ? ? ? 在STL中還提供了另一個模版類:auto_ptr類。主要用于管理動態內存分配。如使用new函數分配堆中的內存,而又不記得回收這部分內存,在會導致內存泄漏。必須使用delete語句釋放該內存塊。即使在函數末端添加了delete語句釋放內存,還需要再任何跳出該函數的雨具(如拋出異常)之前添加釋放內存的處理,例如,goto語句,throw語句。auto_ptr模版定義了類似指針的對象,將new獲得的地址賦給該對象。當auto_ptr對象過期時,析構函數將使用delete來釋放內存。將new返回的地址賦值給quto_ptr對象時,無須記住還需要釋放這些內存。在auto_ptr對象過期時,內存將自動釋放。

三、容器:

? ? ? ? 容器是管理序列的類,通過容器類提供的成員函數,實現各種對序列中元素的操作,是一種高度的泛型抽象。部分算法也可以應用于容器序列的控制。

? ? ? ? STL提供了各種容器的模版類,通常這些模板類包括:向量(vector)、列表(list)、雙隊列(deque)、集合(set)、多重集合(multiset)、映射(map)、多重映射(multimap)。通常,

  • 向量(vector)可以認為是包含一個或者N個更多元素的數組;
  • 列表(list)是由節點組成的雙向鏈表,每個節點包含一個元素;
  • 雙隊列(deque)是包含N個連接的指向不同元素的指針組成的 數組;
  • 集合(set)是由節點組成的,每個節點包含一個元素,節點之間以某種謂詞排序;
  • 多重集合(multiset)是允許存在兩個次序相等的元素集合;
  • 映射(map)是由{鍵,值}對組成的幾個,同樣以某種謂詞排序,謂詞和數據對有某種作用;
  • 多重映射(multimap)是允許鍵對包含相等次序的映射。

? ? ? ? STL在實現諸多容器類的同時,還實現了部分序列式容器的適配器(adapter)。容器的適配器是針對原有的基本容器的不足,對原有基本容器功能的補充。所有的適配器都不提供迭代器,元素訪問通過專有的接口函數實現。

? ? ? ? 容器的概念:

? ? ? ? 在編程實現過程中,可以認為“容器是用來存儲和組織其他對象的對象”。容器適配器嚴格地說并不是容器,而是使用容器的對象,是在容器的基礎上發展起來的。

? ? ? ? 容器的成員:

? ? ? ? 作為容器的成員,必須滿足三個條件:

  • 元素必須是可復制的。所有容器均會產生一份元素副本,不會發生alias現象,在所有容器操作行為傳回的均是其元素的副本。這導致復制構造函數的執行非常頻繁;
  • 元素必須是可指派(assign)的,容器的成員函數以及STL的各種算法(algorithm)均可利用assign()函數為元素設定新值。
  • 元素必須是可釋放的(經過析構函數釋放內存)。使用者從容器中將元素刪除時,容器必須釋放其元素所占的內存。按這種需求,析構函數不能設置為private類型

? ? ? ? 容器的函數:

? ? ? ? 作為容器的成員函數(操作),也具有一定共同具備的能力:

  • 容器均能提供value,而非reference(引用)。涉及元素操作時,元素滿足成員的三個條件;
  • 所有的元素自動形成順序自動形成順序。即按此順序可以多次遍歷所有元素。這些容器均包含可返回迭代器的函數,使用這些迭代器可遍歷元素,這是算法和容器的關鍵接口實現;
  • 函數使用者必須確保傳遞的參數符合要求,否則,可能會導致未定義的行為,通常STL不會拋出異常。

? ? ? ? 容器的種類:

  • 序列式容器(sequence容器),容器中的元素時有序的,但未排序。包含:vector動態數組、deque雙向隊列、list雙向串行;
  • 關聯性容器,容器中的元素都經過排序。包含:set、multiset、map、multimap和hash(哈希)table;
  • 容器配接器,是以某種STL容器作為底,修改其接口,具備各自的特點。包含:stack、queue、priority_queue.。

? ? ? ? 容器的數據結構:

  • string字符串,其內保存字符。string并不是真正的類,而是一個basic——string類的typedef。
  • bitset,其內保存bitset的結構體,每個bit表示一個標志(flag)。其長度便是模板的自變量。
  • valarray,是數學中的線性數列的呈現,其好處是可以像處理單一數值一樣,對整個valarray中每個元素實現運算。

? ? ? ? 序列式容器:

? ? ? ? 對于基本容器,通過增加要求來實現對其的改進。序列是一種重要的改進。6種STL容器(deque、list、queue、priority_queue、stack、vector)都是序列。序列最重要的特點就是可以在首端刪除元素,在尾端添加元素。尤其是雙向序列,允許在兩端添加和刪除元素。序列中包含至少一種迭代器。從而保證元素按特定的順序排列,不會在兩次迭代間發生變化。

  • vector類模版:就像一個動態數組,是典型的“將元素置于動態數組中加以管理”的抽象概念。常用API有push_back()、pop_back()、size()、capacity()、max_size()、reserve()、resize()、empty()等;
  • list類模版:由雙向鏈表來實現,每個節點存儲一個元素。list支持前后兩種移動方向。list和vector類似,提供了對元素的隨機訪問。list的優勢在于任何位置執行插入和刪除動作都非常迅速,因為改變的僅僅是鏈接而已。在list中移動元素要比在vector和deque中快得多。
  • deque(雙端隊列)類模版:提供了對序列隨機訪問的功能,可實現在序列兩端進行快速插入和刪除操作的功能,并可以在需要時修改自身大小。采用動態數組來管理序列中的元素,提供隨機存取,和vector具有幾乎類似接口。其最重要的特征在兩端放置元素和刪除元素都是高效的,原因在于deque型序列開放了序列的兩端,即頭尾均開放,可以實現在序列兩端進行快速的插入和刪除。當需要向序列兩端頻繁地插入或刪除數據時,最佳的容器為deque。

????????關聯式容器:

? ? ? ? 關聯式容器依據特定的排序準則,自動為其元素排序。關聯式容器中的元素都經過排序,是已排序的。所有關聯式容器都有一個可供選擇的template參數,指明排序原則。排序準則以函數形式呈現,用于比較元素值或元素鍵。

? ? ? ? 關聯式容器由二叉樹實作出來。在二叉樹中,每個元素都有一個父節點和兩個子節點;左子樹的所有元素都比自己小,右子樹的所有元素都比自己大。關聯式容器的差別在于元素的類型以及處理重復元素的方式。

  • set是一種隨機存取的容器,其關鍵詞和數據文件是同一個值。set對象中的所有元素必須具有唯一值,即不能包含重復的元素。set對象可以使程序按照次序存儲一組數值,在一個集合中元素既作為存儲的數據又作為數據的關鍵值。集合的本質就是一個有序的排列。
  • multiset是另一種類型的容器,其關鍵詞和數據元素是同樣的值。與set不同的是,它可以包含重復的元素。multiset對象可以使程序按照次序存儲一組數值。
  • map是一種關聯數組容器,包含成對數據的容器,一個值是實際數據值,另一個值是用來尋找數據的關鍵值,一個特定的關鍵詞只能與一個元素相聯系。map是排序結構體,鍵值是獨一無二的。事實上,map的內部結構和set是一樣的。set可以認為是一種特殊的map,其鍵值和實值是同一個。
  • multimap是一種允許出現重復鍵關鍵值的關聯數組容器。與map對象不同,一個關鍵詞可以和多個元素相聯系,multimap允許鍵值重復。’? ? ?

? ? ? ? 特殊容器

  • bitset類模版:bitset創造一個內含位或布爾值且大小固定的數組。當需要管理各種標識,并需要以標識的任意組合表現變量時,即可使用bitset類模版。
  • stack類模版:一個棧容器(后進后出,LIFO),使用函數push()將任意數量的元素置入棧(stack)中,使用函數pop()將元素依次反序地從棧中移除。
  • 隊列queue類模版:FIFO(先進先出)型隊列。隊列和棧的不同之處在于,隊列是雙端的,元素壓入時從一端,元素移除時是從另一端;而棧是單端口的容器,元素的壓入和移除均是從同一端口。通俗的講,queue是典型的數據緩沖區結構。
  • 優先隊列Priorty Queues類模版:其元素根據優先級被讀取。在此隊列中,元素并不是按順序存儲在容器中的,而是按照優先級順序存儲在容器中的。即在此類隊列中,被壓入的元素已經按優先級進行了自動排序。

四、C++中的算法:

? ? ? ? 以有限的 步驟解決邏輯或數學上的問題,稱為算法。具體的算法是指對解題方案準確而完整的描述,是一系列解決問題的清晰指令。算法是用系統的方法解決問題的策略機制。算法能夠實現對于一定規范的輸入,在有限時間內獲取所要求的輸出。一般情況下,算法大致分為基本算法、數據結構的算法、數論與代數算法、計算幾何算法、圖論算法、動態規劃及數值分析、加密算法、排序算法、檢索算法、隨機化算法、并行算法等一系列算法。

? ? ? ? C++標準程序庫也提供了一系列的算法。算法一般被設計用來處理迭代器區間。迭代器是一個“可遍歷STL容器內全部或部分元素”的對象。迭代器的當前值指向容器中的特定位置。STL中算法概念可以理解為使用迭代器處理容器中元素的方法。

? ? ? ? 算法庫簡介:

? ? ? ? STL的算法一般采用“覆蓋(Overwrite)”模式而不是“安插(Insert)”模式。調用時必須保證目標區間擁有足夠的元素空間。當然也可以使用“安插(Insert)”型迭代器訪問容器。

? ? ? ? 為了提高靈活性和功效,STL的算法允許使用者傳遞自定義的操作(函數),方便STL算法調用。這些操作(函數)既可以是一般函數,也可以是仿函數。如返回值是bool類型,稱為條件判斷式。

? ? ? ? 對于算法函數設計,有連個主要的通用部分。首先,這些函數都使用模板來提供通用類型;其次這些函數都使用迭代器來提供訪問容器中數據的通用表示。所以,可以將數值存儲于數組中,或存儲在鏈表中,還可以將對象在樹結構中。

  • 非修改式序列算法:不改動容器中元素次序,也不改動元素值。一般通過input迭代器和forward迭代器完成工作,可用于所有的標準容器;
  • 修改式序列算法:一般不直接改變容器中元素的值,或者在復制到另一區間的過程中改變元素值。修改式序列算法還包括移除性質的算法。移除一般只是在邏輯上“移除”元素,不改變容器的大小和容器中的元素個數。“移除”和“刪除”是不同的算法。
  • 排序和相關算法:包括多個排序函數和其他各種函數,包括集合操作等。C++的STL涵蓋了所有的變序性算法。排序一般是指通過對容器中元素的賦值和交換,改變元素順序。排序算法的復雜度通常低于線性算法,要動用隨機存取迭代器。變序性算法不能以關聯式容器作為目標。因為關聯式容器的元素被視為常數,不能變更。
  • 通用數字算法:一般包括將區間的內容積累、內部乘積、小計、計算相鄰對象差等函數。

? ? ? ? 非修改性序列算法:

  • for each算法:for_each非常方便地同時處理修改每個元素;
  • 元素計數算法:STL算法庫提供了元素計數的功能,即求得容器中元素的總個數。這個功能是由算法count()來實現。另外還提供了條件計數的算法count_if();
  • 最大值和最小值算法:max_element()、min_element();
  • 搜尋算法:find()、find_if()、search_n()、find_en()、find_first_of()、adjacent_find();
  • 區間比較算法:equal()、mismatch()、lexicographical_compare();

? ? ? ? 變動性算法:

????????復制:

  • 如要把一個區間復制到前端,應使用copy(),此目標位置應在_First之前;
  • 如要把一個區間復制到后端,應使用copy_backward()。目標位置-DestEnd應該在sourceEnd之后;
  • STL并沒有提供copy_if()算法。如希望實現現有條件地復制容器中的元素,可以算法remove_copy()_if();
  • 如希望在復制過程中逆轉元素的順序,可以使用reverse_copy();
  • 確保目標區間有足夠空間,否則需要使用insert迭代器;
  • 如實現兩個容器間所有元素的復制,可以不使用copy()和copy_backward(),而使用assign()算法;
  • 如希望在復制過程中刪除部分元素,可使用算法remove_copy和remove_copy_if();
  • 如在復制過程中改變元素的數值,需要使用transform()算法和replace_copy()算法;
  • 如目標容器是空容器,需要使用插入型迭代器(InsertIterator)。

? ? ? ? 轉換:

? ? ? ? STL中提供了函數transform(),實現了將源區間的元素復制至目標區間,復制和修改元素一氣呵成;還可以將兩個區間的元素合并,并將結構寫入目標區間,

? ? ? ? 互換:

????????STL中提供了函數swap()及算法swap_ranges(),用于兩個不同容器對象之間的元素交換。

? ? ? ? 賦值:

? ? ? ? STL提供了fill()、fill_n()、generate(),generate_n();

? ? ? ? 替換:

????????STL提供了replace()替代容器中需要替換的元素;

? ? ? ? 逆轉:

? ? ? ? 逆轉是指將容器或序列中的元素按逆向順序反轉,第一個元素變成最后一個元素,第二個元素變成倒數第一個元素,依次反轉。STL提供了兩個可以實現逆轉功能的算法函數:reverse()和reverse_copy()。

? ? ? ? 旋轉:

? ? ? ? STL提供了對于容器或序列的旋轉算法:即rotate()和rotate_copy()。函數rotate()將容器中的元素或序列看作一個環,旋轉這些元素直至原來middle處元素到達first位置。旋轉運算時使序列中的元素按照一個環的方式旋轉,而不是簡單的左移。rotate_copy()產生一個旋轉后的副本,即在旋轉之后會復制參加旋轉的元素。

? ? ? ? 排列:

  • 排列元素next_permutation():會改變容器(序列)中的元素次序,排序方式為字典式“正規”排序;
  • 重排元素random_shuffle():是指對容器中的所有元素進行隨機排序,一般有兩種形式,符合均勻分布隨機的排序;按指定規則打亂容器(序列)中的元素次序。
  • 前向搬移partition():是按指定的一元判斷式向前搬移元素,當一元判斷式的值為true時,算法會向前移動符合條件的元素,函數返回值是使一元判斷式為false的第一個元素位置。

? ? ? ? 排序及相關操作:

? ? ? ? STL提供了多種算法用來對容器(序列)中全部或部分元素進行排序。

  • 全部元素排序:算法sort()和算法stable_sort()支持對容器(序列)中所有元素進行排序。算法sort()和stable_sort()需要訪問隨機存取迭代器,智能適用于vector型和deque型容器。由于list型容器不支持隨機存取型迭代器,所以不能使用這兩個算法,但是list型容器提供了sort()成員函數,用于自身元素的排序。
  • 局部排序:partial_sort()和partial_sort_copy();
  • 根據某個元素排序:nth_element(),該算法可以對指定區間內的元素進行排序,并使第N個位置上的元素就位。即所有在位置n之前的元素都小于等于它,所有在位置n之后的元素都大于等于它。因此,可得到根據位置N上的元素分割出兩個子序列。第一個序列的元素全部小于第二個子序列的元素。
  • 堆(Heap)操作:“堆”屬于計算機領域的一個術語。在計算機算法領域,“堆”通常用于指一種組織序列元素的方式。“堆”的第一個元素通常時具有最大值的元素。STL的算法庫中提供了部分堆操作算法:push_heap()、pop_heap()、sort_heap()、make_heap()等;堆(Heap)應用與排序,是一種特別的元素組織方式,是以序列式群集實做而成二叉樹。它具有兩大性質:堆中的第一個元素的值總是最大;能夠在對數時間內增加或移除一個元素。
  • 合并排序:set_merge兩個已序集合的總和(merge);set_union()兩個已序集合的并集(union);set_intersection()兩個已序集合的交集(intersection)、set_difference()兩個已序集合的差集(difference)、inplace_merge()連貫的已序區間合并算法。
  • 搜索:binary_search()、includes()、lower_bound()、equal_range()和upper_bound();

? ? ? ? 刪除算法:

  • remove()算法:查找并刪除容器(區間)中的元素時最基本的操作。
  • remove_if()算法:條件刪除算法。
  • remove_copy()和remove_copy_if():用于復制過程中移除相關的元素。
  • unique()移除重復元素:在vector、list、deque、multiset和multimap等類型的容器中,允許元素重復出現,但是有時需要刪除重復的元素。
  • unique_copy()復制過程中移除重復元素;

五、迭代器(Iterator):

? ? ? ? 迭代器是鏈接容器和算法的紐帶,它為數據提供了一種抽象的觀點,使寫算法的人不必關心各種各樣的數據結構和具體細節。迭代器提供了一個數據訪問的標準模型,緩解了要求容器提供一組更廣泛的訪問操作的壓力。

迭代器用對象序列作為它所支持的數據訪問模型。將具體數組和字節形式的低級數據模型映射到高級的對象模型。

? ? ? ? 迭代器及其特性:

? ? ? ? 迭代器本身是一種對象,所以,即使不是迭代器,但其行為類似迭代器的東西,也是迭代器。迭代器不是通用指針,而是指向數組的指針概念的抽象。通俗的講,迭代器就是一個指示器。迭代器技術能夠使程序反復地對STL容器內容進行訪問。當參數化類型為C++內部類型時,迭代器是C++的指針。

  • 輸入迭代器:主要用于為程序中需要的數據源提供輸入接口,此處數據源可以是容器、數據流等。輸入迭代器只能夠從一個序列中讀取數據,此類迭代器可以被修改、引用并進行比較;
  • 輸出迭代器:主要用于輸出程序中已經得到的數據結果,此處結果數據指的是容器、數據流等。輸出迭代器只能向一個序列寫入數據,此類迭代器可以被修改和引用。
  • 前向迭代器:可以隨意訪問序列中的元素,許多STL算法函數需要提供前向迭代器。前向迭代器可以用來讀也可以用來寫,結合了輸入和輸出迭代器的功能,并能夠保存迭代器的值,以便其原先位置開始重新遍歷。
  • 雙向迭代器:既可用來讀也可用來寫,雙向迭代器可以被增值和減值,并且可以同時進行前向和后向元素的操作。所有的STL容器都提供了雙向迭代器功能,以有利于數據的寫入和讀出。
  • 隨機訪問迭代器:可以通過跳躍的方式訪問容器中的任意數據,從而使數據的訪問非常靈活。隨機訪問迭代器作為功能最強大的迭代器類型,具有雙向迭代器的所有功能,能夠使用算法和所有的迭代器比較功能。

? ? ? ? 迭代器類型詳述:

  • 輸入型迭代器(InputIterator):只能一次一個地向前讀取元素,并按此順序傳回元素值。InputIterator迭代器只能讀取元素一次。如復制輸入型迭代器,原InputIterator迭代器和新產生的副本都向前讀取,會遍歷到不同的值。所有的迭代器都具備輸入型迭代器的能力,純粹代器的迭代器的典型例子是“從標準輸入裝置讀取數據”的迭代器。同一個值不會被讀取兩次,一旦輸入流讀入一個字后,下一次讀取時就會回傳另一個字。
  • 輸出型迭代器(OutputIterator):其作用是將元素值逐個寫入,即只能逐個元素進行賦值,不能使用OutputIterator型迭代器對同一序列進行兩次遍歷。
  • 前向迭代器:是輸入型迭代器和輸出迭代器的結合,具有輸入型迭代器的全部功能和輸出型迭代器的大部分功能。
  • 雙向迭代器:在前向迭代器的基礎上增加了回頭遍歷的功能。可支持遞減運算符,可以實現一步一步的后退操作。
  • 隨機存取迭代器:在雙向迭代器的基礎上增加了隨機存取能力。因此,必須增加(提供)迭代器算數運算。即可以實現迭代器加減某個偏移量、能處理距離問題。

? ? ? ? 迭代器配接器:

? ? ? ? C++標準程序庫提供了多個預先定義的特殊迭代器,即所謂迭代器配接器(iterator adapters)。迭代器配接器使算法能夠以逆向模式、安插模式進行工作,還可以和流配個。迭代器配接器不僅能起輔助作用,還能賦予整個迭代器抽象概念更加強大的能力。

  • 逆向迭代器(Reverse):能重新定義遞增運算和遞減運算,使其行為正好倒置。算法以逆序次序來處理元素。所有標準容器都允許使用Reverse迭代器來遍歷元素。
  • 插入型迭代器(Insert):用來將“賦值新值”操作轉換為“安插新值”操作。通過迭代器,算法可以執行安插行為而非覆蓋行為。所有Insert迭代器都隸屬于Output迭代器類型,它只提供賦值新值的能力。
  • 流迭代器:是一種迭代器配接器,可以把流當成算法的原點和終點。流迭代器是特殊用途的輸入和輸出迭代器,程序能管理與I/O流相關的數據。插入和反向迭代器由迭代器適配器形成。一個istream迭代器可以用來從input stream中讀取元素,而ostream迭代器可以用來對output stream寫入元素。流迭代器的特殊形式是所謂的stream緩沖區迭代器,用來stream緩沖區進行直接讀取和寫入操作。

? ? ? ? 迭代器輔助函數:

  • advance()迭代器前進函數:可使相關的迭代器前進和后退,增加的速度由參數決定,可以使迭代器前進和后退一個或多個元素。
  • distance()迭代器距離:用來處理兩個迭代器之間的距離。
  • iter_swap()交換兩個迭代器所指內容:用來交換兩個迭代器的元素值,迭代器的型別不一定相同,但所指向的兩個數必須可以互相賦值。

六、STL的數值計算:

? ? ? ? C++ STL標準程序庫的數值相關組件,其中包括復數(complex)、數值數組(value arrays),以及從C標準程序庫繼承而來的全局數值函數。

? ? ? ? 復數運算:

? ? ? ? C++標準庫中提供了一個template class complex<>,用于實現復數操作。復數是由實部和虛部組成的數值。虛部特點是“其平方值為負數”。即復數虛部帶著i,i是-1的平方根。

? ? ? ? 復數類complex的成員函數包括:構造函數、實部函數(real)和虛部(imog),運算符函數。

? ? ? ? 復數還可以進行其他一些簡單的運算,如:絕對值函數(abs)、絕對值的平方(norm)。復數的相位(arg)、輸入與輸出、共軛函數(conj)、極坐標函數(polar)等。

? ? ? ? 數組(向量)運算:

? ? ? ? STL提供了一個數組類,class valarray。類valarray用于實現數值的運算。valarray代表一個數學概念:數值線性序列。該序列是一維的,但可以通過運用特殊技巧得到多維效果。所謂的特殊技巧,即使用“索引”能力和強大的“子集”能力。因此,valarray是向量和矩陣運算的基礎。數值計算工作多依賴于浮點數值的一維向量,下標從零開始。類valarray的設計目的就是加速常用數值向量的計算。

? ? ? ? 通用數值計算:

? ? ? ? 在STL中,按照<algorithm>中非數值算法的風格,提供了4個通用的數值算法。這4個算法的聲明在頭文件<numeric>中。包括:accumulate()(求和)、inner_product()(內積)、partial_sum()(部分和)和adjacent_difference()(序列相鄰差)。

? ? ? ? 全局性數學函數:

? ? ? ? C++全局函數在頭文件<cmath>和<cstdlib>中。

七、輸入/輸出流:

? ? ? ? ? ? 標準程序庫中的IO classes不僅局限于文件、屏幕或鍵盤,它形成了一套富有彈性的框架,用于任意數據格式化,處理(存取)任意外部表述。

? ? ? ? IOStream簡介:

? ? ? ? Stream對象:

  • 輸入流和輸出流:C++ IO由stream完成。所謂stream是一條數據“流”,字符序列在其中“川流不息”。按面向對象的原則,stream是由某個類別定義出來的具有特定性質的對象。
  • 文件流對象:用于文件操作時,程序需要實例化文件流類的對象,文件流類包括3個,ofstream、ifstream和fstream?。這3個對象分別支持文件輸入、輸出以及兼具輸入和輸出。程序需要再流類的構造函數中包括實參,或者實例化未初始化的文件流對象。? ? ? ?

? ? ? ?Stream類別:

  • ?class istream,定義input stream,可用來讀取數據;
  • ?class ostream,定義output stream,可用來寫出數據;
  • class ofstream,實現文件輸入和輸出。

? ? ? ? IOStream基本類和標準IOStream對象:

  • 輸入函數:get(s,num)、get(s,num,t)、getline(s,num)、getline(s,num,t)、read(s,num)、readsome(s,num)。
  • 輸出函數:write()和flush()。

? ? ? ? 格式化:

? ? ? ? 對于格式化IO輸出,最重要的是格式標志,可定義諸如:數字精度、充填字符、數字進制等。

? ? ? ? StreamBuffer緩沖區類:

? ? ? ? 通常,stream并不負責實際讀寫操作,而是委托給stream buffer實現。輸出流將某些字符放入緩沖區,之后某個時刻,這些被寫到輸出設備上。此類緩沖區可被稱為Streambuf。類Streambuf為緩沖區管理內存,并提供用于填充的緩沖區、訪問緩沖區內容、刷新緩沖區和管理緩沖區內存的類方法。

? ? ? ? 基于字符串的流:

? ? ? ?在STL的頭文件<sstream>中定義了4個類模版和6個類型,均是和basic_string相關的流緩沖區類型。其功能主要是實現將流附著在string上,即通過流所提供的格式化功能,從string中讀取或寫入string。

  • streambuf類:
  • 類模版basic_istringstream:支持讀取basic_string類的對象。使用basic_stringbuf類對象控制相關的存儲區域。
  • 類模版basic_ostringstream:支持寫入basic_string類的對象。使用basic_stringbuf類對象控制相關的存儲區域。
  • 類模版basic_stringstream:支持讀取和寫入basic_string類對象。

? ? ? ? 基于文件的流:

  • template class basic _ifstream<>及其特化版本ifstream和wifstream,用于讀取文件;
  • template class basic _ofstream<>及其特化版本ofstream和wofstream,用于將數據寫入文件。
  • template class basic _fstream<>及其特化版本fstream和wfstream,用于讀寫文件。
  • template class basic _filebuf<>及其特化版本filebuf和wfilebuf,被其他的file stream classes用于進行實際字符的讀寫工作。

八、異常處理:

? ? ? ? 異常處理是一種C++特性。異常處理將會使程序按照有序、有組織和一致的方式截取和處理異常條件——錯誤。異常處理允許使用一段程序來感知和分發錯誤條件,用另外一段程序來處理錯誤。檢測錯誤的代碼可能不知道處理的策略,代碼可以是庫中的類和函數,也可能包含其他種類的處理錯誤的代碼。通常錯誤來源于程序的隱含錯誤或致命錯誤(無效等)。函數庫不可能知曉所有能檢測出的可能發生的異常。函數將錯誤匯報給正在使用的程序,需要一定的前提。

? ? ? ? 異常概念及基本思想:

? ? ? ? 異常的分類:

  • C++標準程序庫可以在“不污染”函數接口的情況下處理異常。一旦遭遇異常情況,通過“拋出異常”停止正常的處理過程。語言本身或標準程序庫所拋出的所有異常,均派生于基類exception。
  • 語言本身支持的異常:bad_alloc異常、dynamic_cast通常拋出bad_cast異常、typeid會拋出bad_typeid異常、非預期的異常bad_exception會及時處理,函數bad_exception會調用unexpected()。
  • C++標準程序庫發出的異常:派生于logic_error,邏輯異常類別,invalid_argument、length_error、out_of_range、domain_error。
  • 程序作用域(scope of program)之外發出的異常:派生于runtime_error的異常,用來指出“不再程序范圍內,且不容易回避”的事件。

? ? ? ? 異常的捕捉和處理:

  • 全局宏errno表里、零或錯誤函數的返回值來報告錯誤種類,方法可靠但非常繁瑣。
  • 使用setjmp()和longjmp()函數:能夠依次、自動地把堆棧還原至函數調用層次結構中較高層位置所記錄的狀態。會截取和處理不需要瞬時終止程序的錯誤條件。
  • 使用try塊和catch塊處理異常的捕捉和處理;
  • 資源管理:當函數申請了其所占有的資源時,為保證系統的運行,必須正確地釋放此資源。
  1. 構造函數和析構函數的使用:當某個對象的構造執行完畢時,此對象才被認為已經明確建立。之后,堆棧回退時才為該對象調用析構函數。由子對象組成的對象的構造函數需要等待所有子對象的構造函數均完成執行才完畢;
  2. STL的auto_ptr類:可以使用指針去初始化,且能夠以與指針同樣的方式間接訪問。在auto_ptr類對象退出作用域時,所指的對象被隱式地自動刪除。
  3. 構造函數中的異常和new:“資源申請即初始化”技術是最安全最優秀的方法。從根本上講,該技術把處理多種資源的問題,歸結為一種反復應用處理單一資源技術的問題。
  4. 析構函數中的異常:不能讓析構函數拋出異常,如真的在析構函數中發生了異常的拋出,即是異常處理機制的重大失敗。
  5. 資源耗盡:
  • 異常的描述:異常描述檢查、未預期的異常、異常映射。
  • 未捕捉的異常:未捕捉的異常是沒有為其準備catch()處理函數的異常,或是throw()所執行的析構函數拋出異常。此異常將造成terminate()函數被調用,該函數調用abort()以終止程序。

? ? ? ? 異常類及幾個重要問題:

? ? ? ? 類exception,函數abort(),堆棧解退,錯誤代碼,異常的迷失,異常處理的局限性。

????????類exception:

????????類exception除了提供構造函數、析構函數之外,僅有一個虛成員函數what()。函數what()用以獲取“型別本身以外的附加信息”,函數返回值是一個以null結束的字符串。

  • domain_error類:數學函數通常有定義域和值域。定義域由參數的可能值組成,值域由函數可能的返回值組成。
  • invalid_argument類:指出給函數傳遞一個意外的值。
  • length_error類:用于指出沒有足夠的空間來執行所需的操作。
  • out_of_range類:指示索引錯誤,即索引的數值超出了正常容量的上下限。
  • runtime_error:描述了可能在運行期間難以預計和防范的錯誤,每個類的名稱指出其報告的錯誤類型。
  • bad_allloc異常和new:

? ? ? ? 調用abort():

? ? ? ? 終止程序,之后函數的返回值會通知操作系統處理失敗,abort()是否要刷新文件緩沖區取決于實現。有時,也可使用函數exit()。函數exit完成刷新緩沖區的功能,但不顯示消息。

? ? ? ? 堆棧解退:

? ? ? ? 假定函數出現異常而終止,則程序將釋放堆棧中的內存,但不會釋放堆棧內第一個返回地址,而是繼續釋放堆棧,直至尋找到try塊中返回的地址。之后,控制權將轉到塊尾的異常處理程序,而不是函數調用后面的第一條語句。該過程稱為堆棧解退。

? ? ? ? 異常處理的局限性:

? ? ? ?處理異常詳述:

? ? ? ? 異常處理的基本思想是簡化程序的錯誤代碼,為程序健壯性提供一個標準檢測機制。

? ? ? ? 異常機制的規則:

  • 異常機制只能用于處理錯誤;
  • 通常不要使用goto語句或switch語句跳轉至try塊或catch塊內;
  • 不要顯示地拋出NULL;
  • 如函數聲明時,指定了具體的異常類型,只能拋出指定類型的異常;
  • 如函數聲明時指定了異常類型,在編譯單元中該函數的聲明必須有同樣的指定;
  • 異常只能在初始化之后且程序結束之前拋出;
  • throw語句只能出現在catch語句塊中;
  • 空的throw語句本身不允許引發新的異常;
  • 所有的流程中顯式地拋出異常應該有一個類型兼容的處理程序;
  • 至少需要有一個程序處理所有其他針對處理的異常;
  • 若try-catch語句塊中有多個處理程序,或派生類和部分或全部基類的function-try-bloack塊有多個處理程序,處理程序的順序應該是先派生類后基類;
  • 如try-catch語句塊或function-try-bloack塊有多個處理程序時,catch(....)處理程序(捕捉獲取所有異常)應該放在最后;
  • 若異常對象為類的對象時,應該通過引用來捕獲;
  • 若構造函數和析構函數時function-try-bloack結構的,在catch處理程序中不能引用該類或基類的非靜態成員;
  • 析構函數退出之后,不允許還有未處理的異常。

? ? ? ? 異常處理的特殊函數:

? ? ? ? 函數terminate():

? ? ? ? 下述情況下,異常處理必須被放棄,而采用較弱的錯誤處理方式:

  • 當異常處理機制調用的用戶函數包括一個uncaugth_exception時,在拋出完整的信息之后,異常被捕獲之前的時間段內;
  • 當異常處理機制不能發現拋出的異常句柄時,堆棧中退出的對象的析構函數存在一個異常時;
  • 當函數被執行時,而此函數使用atexit注冊過;
  • 當一個拋出的表達式嘗試重新拋出異常并且沒有異常被處理時;
  • 當unexception函數拋出一個異常,而該異常不被前面的異常說明允許,并且std::bad_exception不包括在異常描述中;
  • 當默認的unexception_handler被調用時。
????????unexceptected()函數:

? ? ? ? 如一個函數帶有一個異常描述,拋出異常時,異常描述沒有被列表,則函數void?unexceptected()被迅速調用。unexceptected()函數不應該返回,但它能拋出一個異常。

? ? ? ? 函數uncaught_exception():

? ? ? ? 此函數放在析構函數中。返回為true,被拋出的對象被評估之后,直到相匹配的句柄完成異常聲明初始化。它包括了退棧的過程。如異常被重復拋出,重新拋出異常之處,uncaught_exception()返回為true,直到重新拋出的異常被再次捕獲。

九、通用工具:

? ? ? ? C++標準庫的通用工具由短小精悍的類和函數構成,執行最一般化的功能。頭文件<unility>是很小的頭文件。

? ? ? ? 動態內存管理:

? ? ? ? 在STL中,頭文件<memory>以非常杰出的方式為容器中的元素分配存儲空間,同時也為某些算法執行期間產生的臨時對象提供機制。在C++標準中,提供了內存分配器(allocator)。

  • 默認分配器:在名稱空間std中,聲明了一系列和內存管理相關的模板類、模版函數、緩沖區模版類、迭代器和算法。
  • raw storage iterator:用于使算法可以存儲其結果至非初始化的內存。
  • temorary buffers(臨時緩沖區):

? ? ? ? 堆的內存分配:

? ? ? ? C++程序從存儲器的全局存儲區分配和釋放動態存儲塊;全局存儲區有時稱為自由存儲器(free store),更通用的稱呼是堆(heap)。運用運算符new從對配存儲器,用運算符delete把存儲器返回給堆。

  • new和delete運算符:new運算符和數據類型、類、結構或數組的名字一起使用。會為新建項目分配存儲器并返回存儲器位置,程序可以把返回的地址賦予指針。delete把之前分配的存儲器返回給堆,操作數必須是以前分配的存儲器地址。存儲器返回之后可以運算符重新分配。
  • 分配固定維數的數組:
  • 分配動態內存數組:
  • 處理堆耗盡:通過將try塊和catch塊放在main()函數中,至少可以將異常截獲。

? ? ? ? 輔助功能:

  • 數值極限:數值型別的極值是與平臺相關的特性;
  • 最大最小值(較大較小值):max()、min();
  • 兩值交換:swap();
  • 輔助性比較;

? ? ? ? 日期和時間:

  • asctime():用于將指定的時間以字符串(英文簡寫)形式輸出;

  • ctime():用于將指定的時間以字符串形式輸出,并遵循從本地時區設置;

  • clock(0:返回值是硬件滴答數,需要換算成秒或毫秒;

  • difftime():返回兩個time_t類型參數(時刻)之間的時間差;

  • gmtime():用于將參數傳遞的時刻轉換為格林尼治時間;

  • localtime():把從1970年1月1日零時零分到當前時間系統所偏移的秒數時間轉換為日歷時間;

  • mktime():將當前的日歷時間轉換為從1970年1月1日零時零分起至今的UTC時間經過的秒數;

  • time():獲取當前系統(電腦)時間;

  • strtime():根據區域設置格式化本地時間、日期,函數的功能將時間格式化。

? ? ? ? 模版類auto_ptr:

? ? ? ? 使用auto_ptr使用函數new()將指針存儲在一個對象中,當需要被破壞此指針時,使用delete()函數。模版auto_ptr_ref保持了對類auto_ptr的一個引用。該引用用于允許auto_ptr類型對象的傳遞和從函數中傳遞出來。

????????

十、語言支持:

十一、檢測庫詳情:

? ? ? ? 異常類Exception:

? ? ? ? 標準C++庫提供諸多的類,用于在C++程序中報告某些確定的錯誤。這些錯誤的模型反映(折射)了這些類,錯誤被分成兩個大類:邏輯錯誤和運行錯誤。邏輯錯誤的特性是:這些錯誤的 原因是程序的內部邏輯錯誤。從理論上講,這些錯誤是可以被預防的。相反,運行錯誤的原因上通常時一些超出程序范圍的事件。此類錯誤不容易被提前預知。

  • 類logic_error:定義了異常對象的類型,這些異常對象被拋出用于報告程序執行過程中發生的錯誤。
  • 類domain_error:是類logic_error的派生類。因此繼承了logic_error類的what()函數。類domain的作用是定義了異常對象的類型,便于在程序執行時報告“域”錯誤;
  • 類invalid_argument():派生于logic_error,定義異常對象的一種類型,該異常對象被拋出時用于匯報一個無效參數錯誤;
  • 類length_error:定義了異常對象的類型,在程序執行時,這些異常被拋出用于長度錯誤。所謂長度錯誤是對象的長度超越了其最大允許的大小;
  • 類out_of_range:定義了異常對象的類型,該對象在程序執行過程中被拋出,用于報告參數值錯誤(該參數不再期望的范圍內);
  • 類runtime_error:定義了異常對象類型。這些異常對象在程序執行時被拋出,用于報告檢測到的錯誤;
  • 類range_error:在程序執行時,尤其是內部計算時,這些異常對象被拋出用于報告范圍類型的錯誤;
  • 類overflow_error:這些異常對象會在發生算術運算溢出錯誤時被拋出;
  • 類underflow_error(下溢出):程序執行過程中,一旦發生算術underflow錯誤,這些異常對象被拋出;

? ? ? ? assertions(斷言):

? ? ? ? 宏assertions會判斷程序中是否出現明顯非法數據,若出現了則終止程序以免導致嚴重后果,便于查找錯誤。

? ? ? ? 使用assert()缺點是會影響程序的性能,增加額外的開銷。

????????assert()需要注意一下幾個問題:

  • 使用斷言捕捉不應該發生的非法情況。不混淆非法情況與錯誤之間的區別,后者必然存在的并且是一定要進行處理;
  • 使用斷言時,應對函數的參數進行確認;
  • 編寫函數時,要反復考查,堆設定的假定需要使用斷言進行檢查;
  • 通常程序員都熟悉部分放錯誤性的程序設計,記住此風格會隱藏錯誤。當進行防錯誤性編程時,若不可能發生的事情卻發生了,需要使用斷言進行報警;
  • 每個斷言需要詳細、清楚;
  • 使用不同的算法對程序結果進行確認;
  • 在錯誤發生之前,即使用初始檢查程序。

? ? ? ? 錯誤編碼:

? ? ? ? 在頭文件<cerror>中,包含了多個錯誤編碼。變量errno的值是常量,在不同的錯誤條件下或事件中,諸多的錯誤代碼被賦值給變量errno。

十二、國際化庫詳解:

????????

十三、仿函數:

? ? ? ? 仿函數也稱為函數符,是以函數方式與括號()結合使用的任意對象。在STL的標準中,仿函數的英文名稱為FunctionObjects,即函數對象。更通俗地說,仿函數是將函數作為參數傳遞的使用方式。

? ? ? ? 仿函數的概念:

? ? ? ? ? 所謂仿函數是一個定義了operator()的對象。仿函數可以視為一般函數,不同之處在于:仿函數的功能是在其成員函數operator()中實現的。雖然仿函數的定義形式比較復雜,但仿函數的有點有三個方面:

  • 仿函數比一般函數更靈巧,主要是因為仿函數擁有狀態(state)。對于仿函數,可以擁有兩個狀態不同的實體。通常的普通函數是不能實現該目的的;
  • 每個仿函數都有其型別。因此仿函數的型別可以作為模板參數,實現指定某種行為的目的,容器型別不會和具體仿函數有關,而僅僅是該型別的仿函數均可使用;
  • 仿函數要比函數指針的執行速度快得多。在C++規范中,函數調用通常使用指針,當需要調用函數時,只需要函數的地址(名稱)即可。地址調用方法的缺陷是效率非常低,為提高效率需要使用仿函數的形式。定義的仿函數被調用時,是使用運算符operator()的?。通過對運算符進行自定義,能顯著提高效率。

? ? ? ? 仿函數的作用:

  • 作為排序規則;

  • 擁有內部狀態;

  • 算法for_each()的返回值;

  • 作為判斷式。

? ? ? ? 輔助用仿函數:

? ? ? ? ? ?仿函數的組合能很重要,可以從一些軟件組件構造出另一些組件。最簡單的仿函數可以構造出非常復雜的仿函數。一般而言仿函數行為均可借由仿函數的組合而實現。

  • f(g(elem)):這是一元組合函數的最一般形式。一元判斷式被嵌套調用,g()的執行結果作為f()的參數。整個表達式的操作類似一個一元判斷式;
  • f(g(elem1,elem2)):兩個元素elem1和elem2作為參數傳遞給二元判斷式g()。其結果作為參數傳給一元判斷式f()。整個表達式雷士一個二元判斷式;
  • f(g(elem),h(elem)):參數elem作為參數被傳遞給兩個不同的一元判斷式g()和h(),兩者的結果由二元判斷式f()處理;
  • f(g(elem1),h(elem2)):此處參數elem1和elem2作為唯一參數傳遞給兩個不同的一元判斷式g()和h(),兩個結果共同被二元判斷式f()處理。

? ? ? ? 關系仿函數:

  • 等于(equal_to<type>);
  • 不等于(not_equal_to<type>);
  • 小于(less<type>());
  • 大于(greater<type>());
  • 大于等于(greater_equal)和小于等于(less_equal);

? ? ? ?邏輯仿函數:

? ? ? ? 返回bool類型的仿函數稱為謂詞。

  • 邏輯與(logic_and<T>);
  • 邏輯或(logic_or<T>);
  • 邏輯非(logic_not<T>);

? ? ? ?算術仿函數:

  • 加減乘除仿函數(plus<T>、minus<T>、multipies<T>、divides<T>);
  • “求余”仿函數(modulus<T>)和“求反”仿函數(negate<T>);

? ? ? ? 其他類型的仿函數:

  • 證和映射(identity<T>):使用時需要一個參數,返回的是未經任何變化的原參數。
  • 仿函數project1st<Arg1,,Arg2>和project2and<Arg1,,Arg2>:這兩個仿函數接受兩個參數。project1st返回第一個參數并忽略第二參數;project2and返回第二個參數并忽略第一個參數。
  • 仿函數select1st<pair>和select2and:<pair>:select1st返回該pair的第一個元素,select2and返回該pair的第二個元素。
  • 仿函數hash<T>:運算符函數會返回參數為x的hash值;
  • 仿函數subtractive_rng<T>:是一種隨機數發生器。

? ? ? ? 適配器:

  • ?綁定器(binder):通過吧二元函數對象一個實參綁定到一個特殊值上,將其轉換成一元函數對象;
  • 取反器(negator):是將函數對象的值反轉的函數適配器。
  • 成員函數適配器:是成員函數可以被用作算法的參數。當算法需要調用一個標準的操作或自定義操作時,成員函數的使用可以是非常簡便的;
  • 函數指針適配器:使函數指針可以被用作算法的參數。

十四、配置器:

? ? ? ? 空間配置器(allocator)簡稱配置器。空間配置器代表一種特定的內存模型,并提供一種抽象概念,便于將內存的申請轉變為對內存的直接調用。

? ? ? ? 配置器主要用于將算法和容器的實現隔離于物理存儲細節之外。每個配置器均提供了一套分配和釋放存儲的標準方式、一套用于指針類型和引用類型的標準名字。

? ? ? ? 配置是一種純粹的抽象(概念)。C++ STL提供了一個標準配置器。主要目的是為程序員提供更好的服務。程序員還可以根據自己需要,設計和提供自定義的分配器。

????????標準器容器和算法均通過分配器提供的功能獲取和訪問存儲。通過提供新的分配器,為標準容器提供新的不同的存儲使用方式。

? ? ? ? 使用配置器可以實例出容器和其他組件。配置器提供一個接口包括:

  • allocate(int num)(分配);
  • construct(p)(生成);
  • destroy(銷毀);
  • deallocate(p,num)(回收對象)。

? ? ? ? 標準配置器:

? ? ? ? 使用全局的函數opertator new和operator delete分配和回收內存,函數allocate()有可能會拋出bad_alloc類型的異常。

? ? ? ? 對于rebind()類型,是使一個配置器能分配任意類型的對象。

? ? ? ? 自定義配置器:

? ? ? ? 實現一個配置器最主要的是:分配和回收存儲空間。在原有的標準配置器的基礎上,修改配置器的幾個成員函數即可,像max_size()、alllocator()、deallocato()。

? ? ? ? 可將自己在內存分配方面策略體現在3個函數內,像重新運行內存、使用共享內存,或內存映射到面向對象的數據庫中。

? ? ? ? 未初始化的內存:

  • uninitialized_fill(ForwardIerator beg,ForwardItertor end,const T& value):以數值value初始化范圍[beg,end]區間內的元素;函數要么成功,要么沒有影響。
  • uninitialized_fill_n(ForwardIerator beg,size num,const T& value):以數值value初始化從beg開始的num個元素。同樣,函數要么成功,要么沒有影響。
  • uninitialized_copy():以[sourcebeg,sourceend]區間內的元素為根據,將destbeg起始的元素加以初始化。函數要么成功,要么沒影響。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714046.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714046.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714046.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【前端素材】推薦優質電商類后臺管理系統網頁Vuesax平臺模板(附源碼)

一、需求分析 在線后臺管理系統是指供管理員或運營人員使用的Web應用程序&#xff0c;用于管理和監控網站、應用程序或系統的運行和數據。它通常包括一系列工具和功能&#xff0c;用于管理用戶、內容、權限、數據等。下面是關于在線后臺管理系統的詳細分析&#xff1a; 1、功…

前端 css 實現標簽的效果

效果如下圖 直接上代碼&#xff1a; <div class"label-child">NEW</div> // css樣式 // 父元素 class .border-radius { position: relative; overflow: hidden; } .label-child { position: absolute; width: 150rpx; height: 27rpx; text-align: cente…

JavaScript中的this

在實際應用中&#xff0c;了解 this 的行為是非常重要的&#xff0c;特別是在編寫庫或框架時&#xff0c;或者當你需要在回調函數中訪問特定的上下文時&#xff0c;通常推薦使用箭頭函數或者其他方法來確保 this 的正確指向。 在ES6中&#xff0c;this 的值取決于它是如何被調用…

web服務器nginx下載及在win11的安裝

一.背景 還是為了公司安排的師帶徒任務。 操作系統版本&#xff1a;win11 家庭版 mginx版本&#xff1a;1.24.0 二.nginx版本選擇與下載 我之前也寫過下載nginx下載_ngnix stable 下載-CSDN博客 不想看尋找過程的&#xff0c;直接點這里去下載https://nginx.org/download…

Docker 使用原理流程

# docker 是如何來的&#xff1f; a. linux 內核本身支持容器技術&#xff0c;LXC (市面上有很多基于 LXC 開發的容器管理軟件&#xff0c;如創建容器&#xff0c;查看容器&#xff0c;管理容器&#xff0c; docker 作為管理容器的一款代表工具軟件) b. 容器的作用&#xff0c;…

利用python批量將.shp文件轉換坐標生成.geojson文件,再將.geojson轉換成.csv文件,最后將csv文件插入數據庫表

第一步&#xff1a;.shp批量轉.geojson # author: JMY # 創建時間: 2024/2/26 17:12 # 批量將.shp文件生成geojson文件并轉換坐標為3857import os import geopandas as gpd# 定義輸入和輸出文件夾路徑 input_folder shp文件 output_folder geojson文件# 定義輸入和輸出坐標系…

【王道操作系統】ch1計算機系統概述-04操作系統結構

文章目錄 【王道操作系統】ch1計算機系統概述-04操作系統結構操作系統的內核操作系統的體系結構考綱新增內容&#xff08;紅色為全新內容&#xff0c;黃色為原有內容&#xff09;&#xff1a;01 分層結構02 模塊化03 宏內核&#xff08;大內核&#xff09;和微內核04 外核 【王…

redis03 八種數據類型

思維草圖 String類型 字符串類型&#xff0c;是redis中最簡單的存儲類型&#xff0c;可以包含任何數據&#xff0c;例如jpg圖片或者序列化的對象等&#xff0c;底層都是以字節數組形式存儲&#xff0c;最大能存儲512MB的數據。 常用命令 KEY命名規范 加前綴&#xff0c;分…

802.11局域網的 MAC 幀

目錄 802.11 局域網的 MAC 幀 802.11 數據幀的三大部分 1.關于 802.11 數據幀的地址 最常用的兩種情況 2.序號控制字段、持續期字段和幀控制字段 802.11 局域網的 MAC 幀 802.11 幀共有三種類型&#xff1a;控制幀、數據幀和管理幀。 802.11 數據幀的三大部分 MAC 首部&…

總結springboot啟動jar,指定配置文件

第一&#xff1a;覆蓋 -- 覆蓋系統中的文件中的application-dev.yml文件&#xff0c;兩種指定方法都可以 springboot默認優先讀取application.properties>application.yml>指定文件(application-dev.yml) 公共配置可以在application.yml&#xff0c;其他配置在applicatio…

基于 STM32U5 片內溫度傳感器正確測算溫度

目錄預覽 1、引言 2、問題 3、小結 01 引言 STM32 在內部都集成了一個溫度傳感器&#xff0c;STM32U5 也不例外。這個位于晶圓上的溫度傳感器雖然不太適合用來測量外部環境的溫度&#xff0c;但是用于監控晶圓上的溫度還是挺好的&#xff0c;以防止芯片過溫運行。 02 問題…

C# - 類與類之間的繼承關系判斷

Type.IsSubclassof(Type type) 作用&#xff1a;用來確定 一個類是否派生自另一個類/ValueType/Enum/委托 不能用于確定&#xff1a;接口是派生自另一個接口&#xff0c;還是類實現接口 class A{} class B : A{}A a; B b;var boo b.GetType().IsSubclassOf(typeof(A)) // t…

sqllabs第五關floor報錯注入

實驗環境sqllabs第五關 floor()報錯注入的原因是group by在向臨時表插入數據時&#xff0c;由于rand()多次計算導致插入臨時表時主鍵重復&#xff0c;從而報錯&#xff0c;又因為報錯前concat()中的SQL語句或函數被執行&#xff0c;所以該語句報錯且被拋出的主鍵是SQL語句或函…

go語言中的協程和Java中線程以及進程的區別

理解 Go 語言中的協程&#xff08;Goroutine&#xff09;、Java 中的線程和進程之間的區別可以從以下幾個方面來看&#xff1a; 輕量性&#xff1a; Goroutine&#xff08;協程&#xff09;&#xff1a; 協程是非常輕量級的執行單位&#xff0c;創建和銷毀的成本很低。在 Go 中…

深入理解Lambda表達式:基礎概念與實戰演練【第114篇—python:Lambda表達式】

深入理解Lambda表達式&#xff1a;基礎概念與實戰演練 在現代編程語言中&#xff0c;Lambda表達式作為一種輕量級的匿名函數形式&#xff0c;越來越受到程序員的青睞。特別是在函數式編程興起的今天&#xff0c;Lambda表達式在簡化代碼、提高可讀性方面發揮著重要作用。本文將…

C++筆記(六)--- 靜態成員變量/函數(static)

目錄 C語言中靜態變量 C靜態成員變量 C靜態成員函數 C語言中靜態變量 1.函數內部用static修飾的變量&#xff0c;只能在此函數使用&#xff0c;但所修飾的變量不隨函數釋放而釋放&#xff0c;下次調用時的值仍為上次結束時的值2.static修飾的全局變量只能在其定義的文件使用…

華為OD技術面試案例6-2024年

個人情況&#xff1a;西電本&#xff0c;二戰某985基本寄了。知識儲備方面&#xff1a;無任何408基礎&#xff0c;學校開過數據結構課程60分過&#xff0c;python純靠自學&#xff0c;無任何刷題經驗&#xff0c;無項目經驗&#xff0c;簡歷東拼西湊。 大概是12月底和OD聯系&a…

數據可視化原理-騰訊-熱力圖

在做數據分析類的產品功能設計時&#xff0c;經常用到可視化方式&#xff0c;挖掘數據價值&#xff0c;表達數據的內在規律與特征展示給客戶。 可是作為一個產品經理&#xff0c;&#xff08;1&#xff09;如果不能夠掌握各類可視化圖形的含義&#xff0c;就不知道哪類數據該用…

CSP-201712-2-游戲

CSP-201712-2-游戲 解題思路 初始化變量&#xff1a;定義整數變量n和k&#xff0c;分別用來存儲小朋友的總數和淘汰的特定數字。然后定義了num&#xff08;用來記錄當前報的數&#xff09;和peopleIndex&#xff08;用來記錄當前報數的小朋友的索引&#xff09;。 初始化小朋…

MATLAB環境下基于離散小波變換的體外血管圖像處理

下面簡要介紹小波變換的部分應用。 信號去噪。小波去噪是根據有效信號和噪聲信號在小波變換后表現出的不同特性實現的&#xff0c;一般可用于去除語音、圖像、視頻等中的噪聲信號。小波去噪方法根據對小波系數的非線性處理方式分為三類&#xff0c;分別是小波變換模極大值去噪…