1 using聲明
- 方便使用命名空間中的成員,不用每次xxx::yyy
-
頭文件不應該包含using聲明(不經意間包含了一些名字)
2 string
表3.1:初始化string對象的方式 |
|
string s1 |
默認初始化,s1是空串 |
string s2(s1) |
s2是s1的副本 |
string s2 = s1 |
等價於s2(s1) |
string s3(“value”) |
s3是字面值”value”的副本,除了最后空格符 |
string s3 = “value” |
等價於s3(“value”) |
string s4(n, ‘c‘) |
s4初始化為有連續n個字符c組成的串 |
表3.2:string的操作 |
|
os<<s |
將s寫到輸出流os當中,返回os |
is>>s |
從is中讀取字符串賦給s,遇到空白結束,返回is |
getline(is, s) |
從is中讀取一行賦給s,返回is |
s.empty() |
s為空返回true |
s.size() |
返回s中字符的個數 |
s[n] |
返回s中第n個字符的引用,n從0開始計起 |
s1+s2 |
返回s1和s2鏈接后的結果 |
s1=s2 |
用s2的副本代替s1中原來的字符 |
s1==s2 |
|
s1!=s2 |
|
<, <=, >, >= |
|
- string對象會自動忽略開頭的空白(即空格符、換行符、制表符)並從第一個真正的字符開始讀起,知道遇到下一處空白為止。
- getline保留輸入時的空白符,只要一遇到換行符就結束並返回結果,得到的string對象不包含該換行符。
- size函數返回string::size_type類型的值,是一個無符號類型的值,而且能足夠存放下任何string對象的大小。如表達式中已有size()函數就不要再用int了,可以避免混用可能帶來的問題。
-
比較依照字典順序,較短的string每個字符都與較長的一樣,則較短的string小。如不一樣,則為第一對相異字符的比較結果。
處理string中的字符
表3.3:cctype頭文件中的函數 |
|
isalnum(c) |
c為字母或數字時為真 |
isalpha(c) |
字母 |
iscntrl(c) |
控制符 |
isdigit(c) |
數字 |
isgraph(c) |
不是空格但可打印時 |
islower(c) |
小寫字母 |
isprint(c) |
可打印字符(空格或c具有可視形式) |
ispunct(c) |
標點符號(不是控制字符、數字、字母、可打印空白) |
isspace(c) |
空白(空格、橫向制表符、縱向制表符、回車符、換行符、進紙符) |
isuppper(c) |
大寫字母 |
isxdigit(c) |
十六進制數字 |
tolower(c) |
轉小寫 |
toupper(c) |
轉大寫 |
范圍for,適合要處理string對象中每一個字符
- for (declaration : expression) statement
-
expression是一個對象,表示一個序列。declaration定義一個變量,用於訪問序列中的基礎元素。每次迭代,declaration的變量會被初始化為expression部分的下一個元素值。
-
如想改變string對象中字符的值,必須把循環變量定義為引用類型。
-
如果只是處理某些字符,使用下標或迭代器。使用下標時必須清楚地知道它是否在合理的范圍之內。下標可用於訪問已存在的元素。
3 vector
-
早期版本中,vector<vector<int> >,需要添加一個空格。
- 初始化過程會盡可能地把花括號內的值當做是元素初始值得列表來處理。
- 如果循環體內包含有向vector對象添加元素的語句,則不能使用for循環。for循環中預存了end()的值,一旦添加或刪除元素,end()函數的值可能變得無效
初始化的方法
v1, v2(v1), v2=v1, v3(n, val), v4(n), v5{a,b,c...}, v5={a,b,c...}
初始化過程會盡量將花括號內的值當成是元素初始值列表來處理。
列表初始化和聚合初始化
[new] T [object] { arg1, arg2, ... };
- 如果T是aggregate類型,list中的參數對object成員逐個初始化;或者,
- 如果T不是aggregate類型,編譯器查找最匹配list參數的T的構造函數。
值初始化
[new] T [object] {};
如果只提供了元素,而沒給初始值,則進行值初始化。
- 如果T有用戶定義的缺省構造函數,直接調用;
- 如果T有編譯器生成的缺省構造函數,先0值初始化再調用;
- 如果T是內置類型,直接0值初始化。
缺省初始化
[new] T object;
缺省初始化除了在值初始化過程中可能進行之外,也可以以上面形式單獨進行。這種初始化的獨特地方在於,如果T是非class類型,則給出非確定值。兼容C的行為。
零值初始化
static T object;
0值初始化除了在值初始化過程中可能進行之外,也可以單獨作用於靜態(或者線程局部)變量
直接初始化
[new] T [object] ( arg1, arg2, ... );
拷貝初始化
傳參,返回值,=定義
4 迭代器
- 所有標准庫容器的迭代器都定義了==和!=。
- 如果對象只需讀操作而無需寫操作,最好用常量類型cbegin和cend。
- 箭頭運算符把解引用和成員訪問兩個操作結合在一起。
- 任何一種可能改變vector對象容量的操作,比如push_back,都會使得該vector對象的迭代器失效。
- 迭代器之間距離 different_type帶符號整型數。
5 數組
- 數組的大小確定不變,不能隨意向數組中添加元素。不允許拷貝和賦值。
-
理解復雜的數組聲明,默認情況下類型修飾符從右往左依次綁定。最好從數組名字開始由內向外順序閱讀。
int *ptrs[10]; //ptrs是含有10個整型指針的數組 int &refs[10] = ???; //不存在引用的數組 int (*Parray) [10] = &arr; //Parray指向一個含有10個整數的數組 int (&arrRef) [10] = arr; //arrRef引用一個含有10個整數的數組
- 對數組的很多操作,編譯器都是自動將其替換為一個指向數組首元素的指針。
- 當使用數組作為一個auto變量的初始值時,得到的類型是指針而非數組。
- 而使用decltype時則不會發生這種轉換。
數組下標通常定義為size_t類型,機器相關無符號類型,cstddef頭文件中。
指針相減類型ptrdiff_t,帶符號類型,也定義在cstddef頭文件中。
內置的下標運算符所用的索引值不是無符號類型,這一點和vector string不同。
6 C風格字符串
- 使用標准庫string比使用C風格字符串更加安全和高效。
- 出現字符串字面值的地方都可以用 以空字符結束的字符數組來替換。
- 從string返回一個C風格字符串,即返回一個指針指向以空字符結束的字符數組。
- c_str返回的數組不保證一直有效,可能后續操作s的值改變之后,之前返回的數組就失去了效用。想一直使用,最好重新拷貝一份。
用數組初始化vector對象
vector<int> ivec(begin(int_arr), end(int_arr));
盡量使用vector和迭代器,避免使用內置數組和指針。盡量使用string,避免C風格的基於數組的字符串。
7 多維數組
范圍for語句,把循環控制變量聲明成引用類型,除了最內層的循環外
1是因為要改變元素的值
2是為了避免數組被自動轉化成指針,導致內層循環不合法
3避免對元素的拷貝。