c++ primer version-5 的整理ios
section 1:c++
內置類型和自定義類型;正則表達式
main函數的返回值:指示狀態。0:成功;1:系統定義。算法
unix和win系統中,執行完程序可使用echo命令獲得返回值。編程
編譯器不一樣?數組
iostream有四個IO對象,cin,cout 和 cerr clog (能夠往流中寫入數據)app
輸出運算符 << 的左側必須是ostream對象,右側爲要打印的值,若是不是內置的類型,則須要運算符的重載(友元、成員函數,寫法?);endl 除告終束該行,還能夠刷新流,將buffer內容刷到設備;dom
命名空間,用於避免名字定義的衝突ide
當cin>>object做爲循環斷定條件時,效果是檢測流的狀態。有效:未遇到錯誤;無效:遇到無效輸入 or 遇到文件結束符(eof:win使用ctrl z,unix 用 ctrl D)函數
edit-confile-debug 逐個修正bug
頭文件的引用:若是是標準庫,用<>,若是不是,使用"xx.h "
文件重定向:命令行 exefile_name <infile>outfile
----------------------------------------
section 2:變量與基本類型
int long 4B 以及long long 8B 的長度;當運算同時有帶符號和不帶符號的數,會轉化爲不帶符號
可尋址最小單元 字節;存儲基本單元 字(看計算機是64bit的)
0開頭8進制;0×開頭16進制
浮點數,指數部分用e表示,默認字面值是double
轉義:經常使用的有 換行 \n
建議初始化每一個內置類型變量
分離式編譯——聲明和定義;使用 extern 表示不定義,不初始化變量
命名規範:自定義類名大寫開頭,變量名小寫
引用(這裏指左值引用)必須初始化,須要且只能綁定在對象上,引用即別名
空指針 NULL(至關於用0初始化指針) or nullptr(新標準,特殊類型字面值,推薦使用)
void* 指針:存聽任意類型對象的地址,只能拿來做比較,or 賦值給另外的void×指針。不能操做該類指針的對象,由於只表示內存空間
const 對象必須初始化,若是想在多個文件間共享const對象,須要在定義前加extern
若是引用指向的是常量,則應該申明爲常量引用 ;若是不是,那麼對於它的常量引用不能經過引用來修改它的值,只能經過它自己修改,就是說const int & num 和 int const & num(不能修改引用指向的值)不一樣
常量指針:頂層const(常量指針):int * const p,表示指針自己是常量,不能修改指針指向另外的對象;底層const(指向常量的指針),修飾的是*p,不能修改指向的值*p,能夠換對象
aoto會忽略掉頂層const的特性
decltype 類型指示符,decltype(a) r,將r的類型設爲a的類型,
constexpr(c++11) 常量表達式 會檢查是否是常量表達式,在編譯時會計算
typedef or using(新標準) 別名
頭文件不能被定義兩次——頭文件保護符——#ifndef #define #endif
----------------------------------------------
section 3:字符串、向量、數組
頭文件不用using namespace的聲明
string s(n,'c') 結果爲n個c的串;初始化使用等號的是拷貝初始化
字符串能直接比較,getline(is,s)從is中讀取一行給s
empty函數和size函數;size函數返回size_type類型變量,是無符號整型數,注意unsigned 數和整型數比較和運算
處理字符:cctype中包含了不少比較函數,例如isalpha(c)若是是字母時爲真,tolower(c)若是c是大寫字母,輸出對應小寫字母,不然原輸出
vector就是個類模板,建立時須要實例化,初始化方式;使用範圍for時,vector的遍歷序列大小不能發生改變;
迭代器的目的是通用,全部stl容器均可以使用;能夠用auto變量指向 容器的begin or end返回值
字符數組 注意要留1個單位來保存空字符\0
數組也可使用begin和end函數獲得指針,end(a)表示a中最後元素的下一位置的指針
指針運算獲得的類型是 ptrdiff_t 定義在cstddef頭文件與機器相關的類型,是帶符號的
strlen strcmp strcat strcpy 都是c風格的函數,c風格使用字符數組表示字符串,這在c++中也能夠操做,且不少能夠兼容運算,但不推薦
-----------------------------------
section 4:表達式
邏輯與和或的短路求值
少用++的後置版本,可是在*iter++形式普遍使用
sizeof 返回size_t類型
隱式類型轉換 和 顯式類型轉換:static_cast(除了底層const外的從大類型到小類型的轉換,也能夠找回void×) const_cast(底層const去掉const性質) reinterpret_cast(從新解釋,很容易出錯) dynamic_cast
---------------------------------------
section 5:語句
switch() case : default:
範圍for語句,直接使用auto,若是還須要對變量更改,必須是auto &i
若是拋出了異常,可是沒有catch,那麼最終會轉到terminate的標準庫函數去處理,通常是程序非正常退出
標準異常:定義在4個頭文件中:exception stdexcept
---------------------------------
section 6:函數
傳參:傳值(指針也是拷貝),傳引用(避免拷貝,與實參綁定,c++推薦使用);引用形參還能夠返回額外信息,若是不想改變,則能夠加const
頂層const傳值時會忽略掉,因此儘可能使用常量引用
數組不能拷貝,因此只能傳指針或者引用。因爲指針不知道數組的大小,因此,經過標記或者使用前尾指針or傳遞一個數組大小來解決
數組的引用 表示爲 int (&arr) [10] 必須加括號,一樣指針也是 須要加括號,否則就是10個指針構成的數組
main函數能夠傳參,argc,argv【】;其中argv[0] 表示程序名
若是實參的個數不知道,且屬於同一類型,可使用 initializer_list<T> il 傳參,就至關於vector同樣,是一個靈活的模板類,支持迭代器,不過內部的元素是const類型
省略符形參 僅僅可用於通用的類型
不要返回局部對象的引用或指針
返回值能夠是vector,直接return {元素1,元素2....}
返回數組指針一樣須要加括號:int (*func(int i) ) [10] ,或者使用c++11 尾置返回類型: aoto func(int i) -> int (*) [10]
重載對於頂層const會忽略
auto 和 decltype對於指針和引用的表示仍是須要加 × 和 &的
重載與做用域:c++名字查找發生在類型檢查前,當前做用域內有匹配的名字時,會忽略外層的同名實體
默認實參:申明時直接用=號,省略的只能省略尾部
內聯inline 減小調用開銷,優化規模小的,流程直接的,頻繁調用的函數,尤爲在循環體內;不用於內聯遞歸函數
除了內聯,constexpr能夠用於常量表達式,二者一般放在頭文件內定義
調試幫助:assert預處理宏 NDEBUG預處理變量
函數指針:int (*pt) (int a,int b) ,則pt就是函數的指針,括號不能少;將函數名做爲一個值,它將轉化爲函數的指針
--------------------------
section 7:類
this是一個常量指針,不能改變指向
構造函數初始化列表用:表示,初始化與賦值不一樣,若是構造的時候,有const或者引用對象,他們必須使用初始化列表,而不能經過賦值(先初始化後賦值)構造;初始化順序與定義的前後順序有關
構造函數能夠委託,委託使用的函數放在初始化列表中
若是有動態分配的內存,則慎用默認合成的拷貝賦值和析構函數,使用string vector這種問題會少不少
類 使用class 則默認全部成員是私有的,使用struct,默認是公有的
explicit 禁止單實參的構造函數實施隱式轉換,放在聲明處,能夠顯式轉換使用
聚合類:全部成員是public,沒有定義構造函數,沒有初始值,沒有基類虛函數
字面值常量類,constexpr構造函數:函數體通常爲空,或者只有return語句
static成員函數不能包含和使用this指針,在外部定義靜態函數時,不用寫static,只出如今聲明中
非靜態數據成員不能做爲默認的實參,而靜態數據成員能夠
------------------------------
section 8:IO庫
IO對象無拷貝或賦值
條件狀態:s.eof(); s.fail(); s.good(); s.clear(flags);經常使用的
緩衝區刷新
打開文件 fstrm.open(s);建立打開: fstream fstrm(s);
文件模式:in out app(每次寫操做前定位到文件末尾) trunc截斷文件
strm.str() 函數返回strm保存的string的拷貝
------------------------
section 9:順序容器
list雙向鏈表,forward_list單向鏈表,array(固定大小數組);後兩個是c++11新加的
容器支持的函數:swap以及<=這些運算符,反向容器reverse_iterator rbegin
迭代器 解引用 end實際上是最後一個元素後面的位置;容器初始化,可使用兩個迭代器來拷貝
array定義:array<int,10> arrayname=array1;該式子合法,只要array1也是<int ,10>
順序容器(除了array)外定義了assign,有兩種形式,一種是用迭代器,另一種使用大小-元素
swap函數很快,由於並無元素自己的交換;只有array的swap纔會真正交換;推薦使用非成員函數版本的swap
容器的插入:push_back, emplace_back,push_front(forward_list也支持), insert 多種形式,可用迭代器,或者大小指定範圍和元素;emplace的操做是構造元素,而不是像push和insert同樣拷貝元素
刪除:pop_back pop_front erase
forward_list有它特殊的插入 insert_after 和刪除 erase_after 以及返回head前不存在的元素的迭代器 before_begin() , cbefore_begin(),操做的數都是迭代器後的數
list與forward_list支持特定算法:lst.remove(val), lst.reverse(), 還有merge sort unique 算法
resize(n,t)函數:可能會使以前的迭代器失效;當刪除元素時,尾後迭代器確定失效
容器會有capacity,表示不分配新內存在的容量
額外的string操做:構造函數:s(s1,pos) s(s1,pos,len) 從s1的pos位置開始拷貝len個字符到s 或者使用substr(pos,n)函數,n也能夠省略;除了insert和erase外還支持 append(args) 和replace(range,args)
string搜索:find,rfind,find_first_of,find_last_of,find_first_not_of 函數,若是沒找到會返回npos靜態成員,是個很大的數
string與其餘數值的轉化:to_string(val), stoi(s,p,d) p是位置,d是s表示的進制 stod(s,p)
容器適配器:stack和queue(依靠deque實現,默認),priority_queue(默認vector實現):均可以基於某個容器來直接構造
stack:pop(),push(item),emplace(args),top();
queue:pop, push, emplace, top, back, front
--------------------------------
section 10:泛型算法
迭代器令算法不依賴於容器,算法不改變容器大小,都對一個range進行操做
fill(pos1,pos2,num) 將range內的元素變爲num
back_inserter(容器) 插入迭代器 還有front_inserter
sort(pos1,pos2) unique(pos1,pos2)返回不重複數的end迭代器位置;stable_sort()
lambda表達式(適用於在不多地方出現的簡單操做,適合有捕獲變量場景),可調用的對象,[capture list] (參數) -> 返回值類型 { } ;能夠用auto f=[ ]...來表示一個lambda,捕獲的是局部變量,能夠值=或者引用&捕獲。lambda能夠方便寫在函數的實參裏面,就像函數指針;
若是是經過值捕獲的,可是加了mutable,那麼局部變量的值也是會最終改變的,和不是const &的引用相似
若是不使用lambda,使用函數,可是要捕獲局部變量。可以使用STL中的auto f2=bind(f,_1,_2,...)
迭代器:插入,反向,流,移動迭代器
find_if(beg,end,pred)查找第一個令pred爲真的元素
--------------------------------
section 11:關聯容器
map set的multi-和unordered形式
pair p.first p.second
set中的關鍵字是隻讀的,迭代器是const,因此用cbegin
插入:insert與emplace函數 m.insert({key,val}) 返回的是一個pair(first,second),first指代的是迭代器,second指代是否插入成功,若是重複沒插入則爲false
刪除:c.erase(元素),元素能夠是單/雙迭代器,或者是key
map能夠進行下標訪問,c.[key]
查找:find(key)返回迭代器,若是沒有則返回end()位置 ; count(key)返回出現的次數;lower_bound(k),upper_bound(k), equal_range(k)返回的是等於k元素的範圍,是pair類型
示例程序:文件單詞轉換
#include<iostream> #include<fstream> #include<sstream> #include <map> #include<algorithm> using namespace std; void transform(ifstream &map_file, ifstream &input, ofstream &out){ map<string,string> trans; string key,val,text; while(map_file>>key&&getline(map_file,val)){ if(val.size()>1) trans.insert({key,val.substr(1)}); //skip the ' ' before the val else trans.insert({key," "}); } while(getline(input,text)){ stringstream ss(text); string word; bool flag=true; while(ss>>word){ if(flag) flag=false; else out << " "; map<string,string>::iterator map_it=trans.find(word); if(map_it!=trans.end()) out<<map_it->second; else out<<word; } out<<endl; } } int main(){ ifstream input("input.txt"); ofstream out("out.txt"); ifstream map_file("map.txt"); transform(map_file,input, out); return 0; }
無序容器的輸出可使用範圍for語句 const auto &it: unordered_map;該容器在存儲組織上相似於桶,依靠哈希函數
-----------------------------------------
section 12:動態內存
靜態內存:static變量和全局變量;棧內存:局部變量; 二者都由編譯器自動建立和銷燬
堆:每一個程序有一塊自由空間,動態分配的對象
智能指針(定義在頭文件memory中):負責自動釋放所指向的對象:shared_ptr, unique_ptr; weak_ptr弱引用,指向sharedptr
shared_ptr獨有操做:auto p=make_shared<T>(), p.unique(), p.use_count()
原理:shared_ptr的析構函數會遞減引用計數,若是爲0則會銷燬指向對象,釋放內存
引用計數增長狀況:初始化另外的sharedptr or 做爲參數傳遞給函數 or 做爲函數返回值
減少狀況:被賦予了新值 or 被銷燬
爲何使用動態資源:(1)程序不知道要使用多少對象;(2)不知道所需對象的準確類型;(3)須要在多個對象間共享數據(常見需求)
內存耗盡會拋出bad_alloc異常,動態內存不能不釋放。也不能屢次釋放
p.reset(new xxx)操做,使p指向另外的對象
使用智能指針管理資源,能夠傳遞給它一個刪除器,用於指定析構,能夠是函數指針,也能夠是可調用的lambda
unique_ptr是不支持拷貝的和賦值的,可是也能夠reset或者置空;
weak_ptr是弱共享,不會改變計數值,使用lock()函數來返回一個指向相同對象的shareedptr
allocator類,在memory下,分配未構造的內存,將內存分配和對象構造分離,這樣就能夠按需構造了
-------------------------------
section 13:拷貝控制
拷貝構造函數的第一個參數必須是引用類型
拷貝賦值運算符: Foo & operator=(const Foo&) 最後返回一個*this
析構的順序與構造的順序相反,先函數體,再成員,成員也是逆序的
何時調用析構:變量離開做用域;對象被銷燬;容器被銷燬;delete 某動態生成對象的指針;臨時對象,建立它的完整表達式結束時
析構函數體自身不直接銷燬成員,成員是在析構函數體以後隱含的析構階段被銷燬
法則:(1)須要自定義析構,則也須要拷貝和賦值操做;(2)須要拷貝,則也須要賦值,反之亦然,而析構不必定須要
可使用默認的合成函數,=default;能夠阻止拷貝或者賦值,=delete
賦值函數必定要注意將本身賦值給本身 ,可以正常操做
引用計數是做爲一個指針變量出如今類的成員中的,指向真正的引用計數值
右值引用&&:變量是左值,只有const的左值引用 or 右值引用能夠引用右值
移動move(頭文件utility):比拷貝高效,至關於竊取資源:int &&rr2=std::move(rr1); rr1將會不使用,被銷燬
爲何要移動:拷貝資源有額外的開銷,在這種拷貝不是必需的狀況下,能夠定義移動構造函數和移動複製運算符的類來避免
noexcept:告知標準庫不拋出異常
移動迭代器:解引用返回的是右值引用
引用限定符& or &&
-----------------
section 14:重載和類型轉換
非成員函數的運算符重載:一般在形參上包含不止一個對象;成員函數的重載:通常IO運算符不使用成員函數重載,使用非成員或者友元
ostream &operator<<(ostream &os, const Sals &item)
一些算數或者關係運算符的重載,一般使用非成員,形參使用常量的引用
下標運算符[] 返回的是普通引用或者是常量引用
先後置的++使用成員函數來重載
除了函數指針,lambda外,調用還可使用函數對象類,重載()
類型轉換運算符
賦值,下標,函數調用和箭頭運算符必須做爲類的成員
-----------------------------
section 15:面向對象程序設計
多態-動態綁定-看傳入的對象是究竟是什麼類型的,是基類仍是派生類對象
虛函數-override-當經過指針或引用調用時,會動態綁定,運行時肯定
派生類最好經過調用基類的構造函數來初始化基類中的成員
final 防止繼承
派生類的成員或者友元只能經過派生類對象來訪問基類受保護的成員,不能直接經過基類對象來訪問
友元能夠訪問該類的私有部分
名字查找先於類型的檢查
基類和派生類的虛函數的參數類型必須相同
在容器中能夠存放基類的指針,能夠是智能指針
-----------------------------------
section 16:模板與泛型編程
類型名能夠用class 或者 typename表示 均可以
在實例化模板的時候,才生成代碼,纔會發現不少類型上的錯誤
模板的頭文件一般包括聲明和定義
類模板 template <typename T> class
using能夠來設置模板的別名: using twin pair<T,T> twin<string> str;
靜態變量在模板類中,不一樣模板實例會有各自獨有的static對象,只在相同類型的模板類中共享
默認模板的實參 能夠在typename T 後加 =
普通類中也能夠有成員模板
多個文件實例化相同的模板會有開銷,可使用extern關鍵字標識模板聲明,extern template class Blob<string> 則它會去外邊找已經定義了的該模板定義
引用摺疊:右值引用的右值引用會摺疊成右值引用
move實際上是函數模板,利用引用摺疊
可變參數模板:參數包(模板參數包和函數參數包) template <typename T, typename ... Args> ; void foo(const T &t, const Args& ... rest) ; rest是函數包的名字
STL中算法都是函數模板,容器都是類模板
類型轉換:有標準庫定義的類模板,可將給定的模板類型參數轉換爲一個相關的類型
---------------------------------------
section 17:標準庫特殊設施
tuple相似於pair(頭文件tuple),能夠包含多種不一樣類型的元素;使用aotu item0=get<0> (item)來訪問其中的成員,比較操做要求兩邊成員個數都要相同
可使用tuple來返回多個值,tuple能夠包含在vector中
<bitset>:處理超過最長整形類型大小的位集合 bitset<n> b(u) ;其中 u是unsigned long long 類型,n是位的大小
也能夠從string初始化,可是string 下標最大的數存在bitset的低位(下標爲0)
bitset函數:count:置位的數目;test(pos)是否被置位
正則表達式(頭文件regex)
regex r(pattern) ; smatch results保存結果; regex_search(test_str, results, r) 找到1個就結束
隨機數 random頭文件:隨機數引擎類和分佈類
defaut_random_engine e, e()
uniform_int_distribution<unsighed> u(0,9) u(e)
u和e能夠聲明爲靜態,以保證起始點不一樣。種子的概念,能夠以time爲種子
cin.get(char ch) 讀入一個字符
流隨機訪問:seek和tell 用於文件流
-------------------------------
section 18:用於大型程序的工具
異常 拋出 catch 棧展開 最終到terminate中處理 終止當前程序
析構函數不要拋出本身不能處理的異常
拋出指針要求在對應的代碼存在的地方,指針所指的對象必須在
從新拋出 就是 空throw ,捕獲全部異常就是catch(...)
異常類:派生有runtime_error, logic_error, 異常類體系,使用咱們本身的異常類
命名空間:防止命名污染,經過namespace::來訪問特定的名字(若是有重複)
using聲明: 每次只引入空間內的一個成員,在局部做用域有效;using指示:全部名字可見
using指示多了,則引入的名字也多,名字污染可能嚴重,二義性可能增長;全部有時用聲明比較好
多重繼承中,拷貝構造函數和賦值函數的構造順序都同樣,析構相反
虛繼承:解決基類的多重拷貝,共享的基類子對象爲虛基類;構造順序:先由最底層的派生類調用虛基類的構造函數,再進行間接基類的構造,再直接基類的構造,最後本身的構造;析構相反順序
--------------------------
section 19:特殊工具與技術
RTTI運行時類型識別
基類到派生類的轉換 dynamic_cast:指針類型的轉換,若是不成功返回0;引用類型轉換,不成功拋出bad_cast異常
typeid(e) 返回e的類型,頂層const會忽略; 比較兩個typeid能夠在運行時識別
enum枚舉:限定做用域與不限定的枚舉,枚舉成員是const的;enum intvalue : unsigned long long 在:後能夠加類型
類成員指針:數據成員指針/成員函數指針;
嵌套類:可使用訪問限定符來控制外界對其成員的訪問權限,與外層類是相互獨立的
union:節約空間的類;能夠有多個數據成員,可是在任什麼時候候只有一個數據成員能夠有值;默認公有
匿名union不能包含受保護的成員或私有變量,也不能定義成員函數
局部類:局部類的成員收到嚴格限制,只能訪問外層做用域定義的類型名、靜態變量和枚舉成員,不能那個訪問局部變量;外層函數不能訪問局部類中私有成員
不可移植的特性支持:
位域:一般用無符號類型保存一個位域 unsigned int mode:2;表示2位; 指針沒法指向位域
volatile限定符:當對象的值可能在程序的控制或檢測以外被改變時,告訴編譯器不該對這樣的對象優化
連接指示:使用其它語言的代碼:extern "C " {}