2.變量和基本類型
c++的算術(shù)類型:
類 型 | 含 義 | 最小尺寸 |
---|---|---|
bool | 布爾類型 | 未定義 |
char | 字符 | 8位 |
wchar_t | 寬字符 | 16位 |
char16_t | Unicode字符 | 16位 |
char32_t | Unicode字符 | 32位 |
short | 短整型 | 16位 |
int | 整型 | 16位 |
long | 長(zhǎng)整型 | 32位 |
long long | 長(zhǎng)整型 | 64位 |
float | 單精度浮點(diǎn)數(shù) | 6位有效數(shù)字 |
double | 雙精度浮點(diǎn)數(shù) | 10位有效數(shù)字 |
long double | 擴(kuò)展精度浮點(diǎn)數(shù) | 10位有效數(shù)字 |
一個(gè)char和一個(gè)機(jī)器字節(jié)一樣斟薇,一個(gè)int至少和一個(gè)short一樣大,一個(gè)long至少和一個(gè)int一樣大加匈。
通常float以一個(gè)字(32 bit)表示崖瞭,double以2個(gè)字來(lái)表示,分別有7個(gè)和16個(gè)有效位躏仇。
8位unsigned char 可以表示0到255的值,signed char可以表示-128 到 127腺办。
- 多數(shù)平臺(tái)上int類型占32位焰手,取值范圍為-2147483648 至 2147483647
類型轉(zhuǎn)換
bool b = 42; // b = true
int i = b; // i = 1
i = 3.14; // i = 3
double pi = i; // pi = 3.0
unsigned char c = -1; // 若char占8bit,則c = 255
signed char c2 = 256; // 若char占8bit怀喉,c2的值是未定義的
- 把非bool類型的算術(shù)值給bool類型時(shí)书妻,初始為0則結(jié)果為false,否則結(jié)果為true
- 把bool類型賦值給非bool類型時(shí)躬拢,初始值為false則結(jié)果為0躲履,初始值為true則結(jié)果為1
- 把浮點(diǎn)數(shù)賦值給整型時(shí),只保留整數(shù)部分
- 整數(shù)給浮點(diǎn)數(shù)時(shí)估灿,小數(shù)部分記0
- 給無(wú)符號(hào)類型一個(gè)超出其表示范圍的值時(shí)崇呵,結(jié)果的初始值對(duì)無(wú)符號(hào)類型表示數(shù)值總數(shù)取模后的余數(shù),例如給8bit的unsigned char(可以表示0到255)賦值-1馅袁,結(jié)果為-1%256=255
- 給帶符號(hào)的類型賦值一個(gè)超出它表示范圍的值時(shí)域慷,結(jié)果是未定義(undefined)的,可能會(huì)出錯(cuò)
注意! 帶符號(hào)數(shù)與無(wú)符號(hào)數(shù)運(yùn)算時(shí)犹褒,會(huì)被轉(zhuǎn)化為unsigned抵窒,int a = -1可能會(huì)變成4294967295,切勿混用unsigned類型和signed類型叠骑!
字面值
O開(kāi)頭的數(shù)代表八進(jìn)制數(shù)李皇,0x開(kāi)頭的數(shù)表示十六進(jìn)制,例如整數(shù)20:
20 // 十進(jìn)制
O24 // 八進(jìn)制
0x14 // 十六進(jìn)制
一般復(fù)數(shù)的那個(gè)負(fù)號(hào)不會(huì)存儲(chǔ)在字面值內(nèi)宙枷,作用僅僅是對(duì)字面值取負(fù)
轉(zhuǎn)義序列:
:-:|:-:|:-:
換行符 \n| 橫向制表符 \t |報(bào)警符 \a
縱向制表符 \v| 退格符 \b| 雙引號(hào) "
反斜線\ |問(wèn)號(hào) ? |單引號(hào)'
回車符 \r |進(jìn)紙符 \f|
也可以通過(guò)添加前后綴來(lái)指定字面值的類型:
對(duì)于字符有:
前綴 | 含義 | 類型 |
---|---|---|
u | Unicode 16字符 | char16_t |
U | Unicode 32字符 | char32_t |
L | 寬字符 | wchar_t |
u8 | UTF-8(僅用于字符串字面值常量) | char |
對(duì)于整型和浮點(diǎn)型有:
后綴 | 類型 |
---|---|
u or U | unsigned |
l or L | long |
ll or LL | long long |
f or F | float |
l or L | long double |
變量
變量定義的基本形式:
類型說(shuō)明符 + 一個(gè)或多個(gè)變量名組成的列表(以逗號(hào)分隔掉房,分號(hào)結(jié)束)
-
何為對(duì)象?
對(duì)象(object)是指一塊能存儲(chǔ)數(shù)據(jù)并具有某種類型的內(nèi)存空間
-
對(duì)象初始化
當(dāng)對(duì)象在創(chuàng)建時(shí)獲得了一個(gè)特定的值慰丛,那么這個(gè)對(duì)象被初始化了卓囚,在同一條語(yǔ)句中可以用先定義的變量值去初始化后定義的變量。
double price = 100.1诅病, discount = price * 0.16;
注意初始化不是賦值哪亿!初始化=創(chuàng)建變量的同時(shí)賦予其一個(gè)初值,賦值=擦除對(duì)象的當(dāng)前值以一個(gè)新的值來(lái)代替贤笆。
-
默認(rèn)初始化
變量將被初始化為默認(rèn)值蝇棉,也有可能定義在函數(shù)體內(nèi)部的內(nèi)置類型變量不被初始化
建議初始化每一個(gè)內(nèi)置類型的變量!
聲明和定義的關(guān)系 *
c++采用分離式編譯機(jī)制芥永,允許將程序分割為若干個(gè)文件篡殷,每個(gè)文件可以被獨(dú)立編譯
為了支持分離式編譯,c++將聲明和定義區(qū)分開(kāi)
聲明(declaration)使名字為程序所知
定義(definition)負(fù)責(zé)創(chuàng)建與名字關(guān)聯(lián)的實(shí)體
變量聲明規(guī)定了變量的類型和名字恤左,定義在這方面也與之相同贴唇。但是定義還申請(qǐng)存儲(chǔ)空間,也可能會(huì)為變量賦一個(gè)初值飞袋。
如果想聲明一個(gè)變量而非定義它,需要用到extern關(guān)鍵字链患,而且不要顯示初始化變量。任何包含了顯示初始化的聲明即成為定義!并且變量只能被定義一次坠非,可以被多次聲明兼蕊。
extern int i; //聲明 i 而非定義 i
int j; //聲明并定義 j
extern int k = 1;//定義 k
贸毕!如果要在多個(gè)文件中使用同一個(gè)變量郑叠,就必須把聲明和定義分離。此時(shí)明棍,變量的定義必須出現(xiàn)在且只能出現(xiàn)在一個(gè)文件中乡革,而其他用到該變量的文件必須對(duì)其進(jìn)行聲明,不能重復(fù)定義。
- c++是一種靜態(tài)類型語(yǔ)言沸版,其含義是在編譯階段檢查類型嘁傀。其中檢查類型的過(guò)程稱為類型檢查。我們?cè)谑褂媚硞€(gè)變量前必須聲明其類型视粮。
標(biāo)識(shí)符
由字母细办、數(shù)字、下劃線組成蕾殴。必須以字母和下劃線開(kāi)頭笑撞。
int somename, someName, SomeName, SOMENAME;
并且還有一些保留字。用戶自定義的標(biāo)識(shí)符中不能出現(xiàn)連續(xù)兩個(gè)下劃線钓觉,也不能以下劃線加大寫字母開(kāi)頭娃殖。定義在函數(shù)體外的標(biāo)識(shí)符不能以下劃線開(kāi)頭。
int _ = 1; //是正確的
名字的作用域
作用域以花括號(hào)分隔议谷。
定義在函數(shù)體之外的名字具有全局作用域炉爆,例如main。
相對(duì)的塊作用域
復(fù)合類型
基本數(shù)據(jù)類型 + 類型修飾符 + 變量名
int i = 1024, *p = &i, &r = i;
最好把類型修飾符和變量名寫在一起
-
引用(左值引用)
引用即別名卧晓, 引用必須被初始化
-
指針
定義多個(gè)指針時(shí)芬首,必須每個(gè)變量前面都有符號(hào) *
指針存放某個(gè)對(duì)象的地址,要想獲取該地址逼裆,要使用取地址符(&)
double dval; double *pd = &dval; double *pd2 = pd; int *pi = pd; //錯(cuò)誤郁稍,指針pi的類型和pd不匹配 pi = &dval; //錯(cuò)誤,指針pi的類型和dval不匹配
通過(guò)解引用符(*)來(lái)得到指針?biāo)傅膶?duì)象胜宇。
耀怜!對(duì)于符號(hào)(*, &),在定義時(shí)桐愉,作為聲明的一部分财破;同時(shí)也可以作為解引用符和取地址符。
生成一個(gè)空指針:
int *p1 = nullptr; int *p2 = 0; int *p3 = NULL;
建議初始化所有指針从诲!
把指針用于條件表達(dá)式時(shí)左痢,任何非0指針的條件值都是true。
-
void * 指針
可以用于存放任意對(duì)象的地址系洛,但也只能存儲(chǔ)地址俊性,不能訪問(wèn)內(nèi)存空間中的對(duì)象。
-
指向指針的指針
可以有指向指針的指針的...指針
-
指向指針的引用
相當(dāng)于對(duì)指針的引用
int i = 42; int *p; int *&r = p; // r 是對(duì)指針 p 的引用
要理解 *&r 到底是什么描扯,應(yīng)該從右往左看類型修飾符定页,距離r最近的符號(hào)是&,那么r就是一個(gè)引用绽诚。其余的符號(hào)確定r引用的類型是什么典徊,符號(hào)*說(shuō)明r引用的是一個(gè)指針杭煎。最后int類型說(shuō)明r引用的是一個(gè)int類型的指針。
從右往左看宫峦,很重要岔帽!
const限定符
const類型的對(duì)象一旦創(chuàng)建后其值就不能再改變,所以const對(duì)象必須初始化导绷。
可以用const對(duì)象去初始化其他對(duì)象犀勒,因?yàn)槌跏蓟僮鞑粫?huì)改變本身的值,只是拷貝了值妥曲。
int i = 42;
const int ci = i;
int j = ci;
贾费! 默認(rèn)狀態(tài)下const對(duì)象僅在文件內(nèi)有效,因?yàn)樵诰幾g過(guò)程中檐盟,會(huì)把會(huì)用到該變量的地方都替換成對(duì)應(yīng)的值褂萧。
當(dāng)在多個(gè)文件中,出現(xiàn)同名的const變量時(shí)葵萎,等同于在不同文件中分別定義了不同的變量导犹,都需要進(jìn)行初始化。
如果在多個(gè)文件中羡忘,都要用到同一個(gè)值的const變量谎痢,而且這一變量的初始值不是一個(gè)常量表達(dá)式,又確實(shí)有必要在文件間共享卷雕。一個(gè)解決辦法就是节猿,對(duì)于 const 變量不管聲明還是定義都添加 extern 關(guān)鍵字,這樣就只需要定義一次就夠了漫雕。
// file_1.cc中定義并初始化一個(gè)常量
extern cosnt int bufSize = fcn();
// file_1.h頭文件
extern cosnt int bufSize;
const的引用
稱為對(duì)常量的引用滨嘱,也不能修改它所綁定的對(duì)象。
const int ci = 100;
const int &r1 = ci; //正確
r1 = 42; //錯(cuò)誤浸间,不能修改const對(duì)象
int &r2 = ci; //錯(cuò)誤太雨,試圖讓一個(gè)非常量引用指向一個(gè)常量對(duì)象
嚴(yán)格來(lái)講并不存在常量引用。
對(duì)const的引用可能引用一個(gè)并非const的對(duì)象发框。
int i = 42;
int &r1 = i;
const int &r2 = i; //r2綁定對(duì)象i躺彬,但是不允許通過(guò)r2修改i的值
r1 = 0; // 通過(guò)r1改變了i的值,同時(shí)會(huì)引起r2的改變
r2 綁定非常量整數(shù) i 是合法的行為梅惯。
指針和const
要想存放常量對(duì)象的地址,只能用指向常量的指針仿野,也不能賦值铣减。
const double pi = 3.14159;
const double *ptr = π
同時(shí)指向常量的指針也能指向一個(gè)非常量。所謂指向常量的指針脚作,只是不能通過(guò)這個(gè)指針來(lái)改變對(duì)象的值葫哗,但是沒(méi)有規(guī)定那個(gè)對(duì)象的值不能通過(guò)其他途徑改變缔刹。
const指針
允許把指針本身定為常量,常量指針必須初始化劣针,而且一旦初始化完成它的值(存放的地址)就不能再改變了校镐。
int errNumb = 0;
int *const curErr = &errNumb; //curErr一直指向errNumb
const double pi = 3.14159;
const double *const pip = *pi; //指向常量對(duì)象的一個(gè)常量指針
指針本身是個(gè)常量,可以改變它指向的對(duì)象的值捺典!
頂層const
頂層const 表示指針本身是個(gè)常量
底層const 表示指針?biāo)傅膶?duì)象是個(gè)常量
指針也可以同時(shí)是底層和頂層const
int i = 0;
int *const p1 = &i; //p1的值不能改變鸟廓,頂層const
const int ci = 42; //ci的值不能改變,頂層const
const int *p2 = &ci; //p2的值可以改變襟己,底層const
const int *const p3 = p2; //靠右的const是頂層引谜,靠左的cosnt是底層
const int &r = ci; //用于聲明引用的const都是底層cosnt
在執(zhí)行拷貝操作時(shí),頂層cosnt不受影響擎浴。
另一方面员咽,拷入和拷出的對(duì)象必須具有相同的底層const資格,或兩個(gè)對(duì)象的數(shù)據(jù)類型必須能夠轉(zhuǎn)換(一般非常量可以轉(zhuǎn)換成常量)
就是說(shuō)可以用一個(gè) const int &
去綁定一個(gè)普通的int
對(duì)象
類型別名
兩種方法定義類型別名:
typedef double wages; //wages = double
typedef wages base, *p; //base = double, p = double*
using SI = Sales_item; //SI = Sales_item
注意不是簡(jiǎn)單的替換:
typedef char *pstring;
const pstring cstr = 0; //cstr是指向char的**常量指針**
const pstring *ps; //ps是一個(gè)指針贮预,它指向的對(duì)象是指向char的常量指針
但是上述語(yǔ)句不是簡(jiǎn)單的替換就行的贝室,不等于以下語(yǔ)句:
const char *cstr = 0; //這是指向常量字符的指針,和上面的不同7峦獭;怠!
decltype
類型說(shuō)明符decltype茫藏,作用是返回操作數(shù)的數(shù)據(jù)類型(包括頂層const和引用在內(nèi))
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //正確误趴,x是一個(gè)const int類型
decltype(cj) y = x; //正確,y是一個(gè)const int&务傲,綁定到x
decltype(cj) z; //錯(cuò)誤凉当,z是一個(gè)const int&,必須初始化
注意decltype對(duì)括號(hào)很敏感售葡,如果decltype使用的是一個(gè)不加括號(hào)的變量看杭,得到的結(jié)果就是該變量的類型。如果給變量加上了一層括號(hào)挟伙,這個(gè)變量就變成了一個(gè)表達(dá)式楼雹,表達(dá)式是可以作為賦值語(yǔ)句左值的,因此是一個(gè)引用類型尖阔。
int i = 0;
decltype((i)) d; //d是int&贮缅,必須初始化,報(bào)錯(cuò)
decltype(i) e; //e是int類型
=槿础G垂!雙層括號(hào) decltype((i))
得到的結(jié)果永遠(yuǎn)是一個(gè)引用齿坷,一層括號(hào)只有當(dāng)里面是引用的時(shí)候才是引用桂肌。
預(yù)處理器
一項(xiàng)預(yù)處理功能
#include
数焊,當(dāng)看到#include
標(biāo)記時(shí),會(huì)用指定的頭文件內(nèi)容代替它崎场。-
頭文件保護(hù)符依賴于預(yù)處理變量佩耳,
#define
把一個(gè)名字設(shè)定為預(yù)處理變量,#ifdef
谭跨,#ifndef
分別當(dāng)且僅當(dāng)變量已定義時(shí)干厚、未定義時(shí)為真,這兩個(gè)if直到#endif
指令為止饺蚊。#ifndef SALES_DATA_H #define SALES_DATA_H #include <string> struct Sales_data{ ...; } #endif
F加铡!預(yù)處理變量無(wú)視作用域規(guī)則
3.字符串污呼、向量和數(shù)組
命名空間
使用using聲明
using namespace::name;
//例如 using std::cin;
using std::endl;
作用域操作符 :: 裕坊,含義是編譯器從操作符左側(cè)名字所示的作用域中尋找右側(cè)的那個(gè)名字。例如 std::cin
就是使用命名空間 std 中的名字 cin 燕酷。
一般來(lái)說(shuō)籍凝,頭文件不應(yīng)該包含 using 聲明
標(biāo)準(zhǔn)庫(kù)類型string
#include<string>
定義和初始化:
string s1; //默認(rèn)初始化,s1是一個(gè)空串
string s2 = s1; //兩種拷貝初始化
string s22(s1);
string s3 = "hiya"; //s3是該字符串字面值的副本
string s33("hiya");
string s4(10, 'c'); //s4是10個(gè)字符c組成的字符串
string的操作:
os<<s //流操作苗缩,將s寫到輸出流os中饵蒂,返回os
is>>s //從is中讀取字符串賦給s,字符串以空白分隔酱讶,返回is
getline(is, s) //從is中讀取一行賦給s退盯,返回is
s.empty()
s.size() //返回字符的個(gè)數(shù)!!!!用size
s[n] //返回第n個(gè)字符的引用
s1 + s2 //返回s1與s2連接后的結(jié)果
s1 = s2
s1 == s2
s1 != s2
<, >, <=, >=
如果使用 cin>>str
時(shí),會(huì)自動(dòng)忽略開(kāi)頭的空白(空格泻肯,換行渊迁,制表符等),從第一個(gè)真正字符開(kāi)始灶挟,直到遇見(jiàn)下一個(gè)空白為止琉朽。!稚铣!以空格為分界O淙!
例如輸入" Hello world "
惕医,會(huì)得到"Hello"
讀取未知數(shù)量的string對(duì)象:
string word;
while(cin >> word){
cout << word << endl;
}
讀取一整行:
string line;
while(getline(cin, line)){
cout << line << endl;
}
getline
得到的一行中不包括換行符耕漱,得手動(dòng)加上 endl。 觸發(fā)getline函數(shù)返回的那個(gè)換行符實(shí)際被丟掉了抬伺。
-
size()
函數(shù)返回的是一個(gè)size_type
類型孤个,無(wú)符號(hào)數(shù)!E婕颉F肜稹!注意椒楣,如果表達(dá)式中已經(jīng)有了 size() 類型给郊,就不要用帶符號(hào)的 int 類型了,否則會(huì)轉(zhuǎn)化成無(wú)符號(hào)數(shù)產(chǎn)生意想不到的后果捧灰。
或者可以:
auto len = line.size();
string 的大小比較是對(duì)字典序進(jìn)行比較淆九,對(duì)大小寫敏感,'A' = 65, 'a' = 97
當(dāng)把字符串和字面值相加時(shí)毛俏,必須保證每個(gè) '+' 兩側(cè)至少有一個(gè)是 string 類型炭庙! 字符串字面值和 string 是兩種不同的類型!;涂堋焕蹄!
-
處理 string 中的字符
使用cctype頭文件
isalnum(c) //是字母或數(shù)字 isalpha(c) //是字母 iscntrl(c) //是控制字符 isdigit(c) //是數(shù)字 islower(c) //是小寫字母 isupper(c) //是大寫字母 ispunct(c) //是標(biāo)點(diǎn)符號(hào) ... tolower(c) toupper(c)
-
c++ 版本的C標(biāo)準(zhǔn)庫(kù)頭文件
c語(yǔ)言的頭文件形如
name.h
,而c++則將這些名字去掉了 .h 阀溶,相應(yīng)的增加了 c 字母前綴腻脏,變成cname
。 例如:#include <cmath> #include <cctype>
-
處理字符
c++11 新的范圍for語(yǔ)句:
for (declaration : expression) statement; for (auto c : str) cout<< c <<endl; for (auto &c : str) // 如果要修改字符银锻,必須要引用 c = toupper(c);
下標(biāo)操作([ ]):
第一個(gè)字符
s[0]
, 最后一個(gè)字符s[s.size() - 1]
e.g. 把字符串 s 的第一個(gè)詞改成大寫形式:
for(decltype(s.size()) index = 0; index != s.size() && !isspace(s[index]); ++index) s[index] = toupper(s[index]); //s = "some string", 結(jié)果s = "SOME string"
-
reverse()
函數(shù)c++中永品,
reverse()
函數(shù)是在 <algorithm> 中定義的,用于反轉(zhuǎn)在 [first,last) 范圍內(nèi)的順序击纬。可以用于反轉(zhuǎn) vector 類型鼎姐,或者 string 類型等。
vector<int> v={1,2,3,4,5}; reverse(v.begin(),v.end());//v的值為5更振,4炕桨,3,2殃饿,1 string str="C++REVERSE"; reverse(str.begin(),str.end());//str結(jié)果為ESREVER++C
標(biāo)準(zhǔn)庫(kù)類型 vector
vector(向量)谋作,有時(shí)也被稱為容器(container)。vector 實(shí)際是一個(gè)類模板乎芳,編譯器根據(jù)模板創(chuàng)建類或者函數(shù)的過(guò)程稱為實(shí)例化遵蚜,通過(guò)在模板名字后加上尖括號(hào),在尖括號(hào)內(nèi)填放信息奈惑。
vector<int> ivec;
vector<Sales_item> Sales_vec;
vector<vector<string>> file; // 在早期版本中吭净,要在后面的兩個(gè)>>中加上一個(gè)空格,寫成下列形式:
vector<vector<string> > file;
初始化:
vector<T> v1;
vector<T> v2(v1);
vector<T> v2 = v1;
vector<T> v3(n, val);
vector<T> v4(n); // v4包含了n個(gè)重復(fù)地執(zhí)行了值初始化的對(duì)象
vector<T> v5{a, b, c...}; //列表初始化
vector<T> v5 = {a, b, c...}; //效果同上肴甸,這是c++11的新標(biāo)準(zhǔn)
可以進(jìn)行默認(rèn)初始化寂殉,不含任何元素。
在進(jìn)行值初始化時(shí)原在,可以不加值具體是什么友扰,只寫入數(shù)字彤叉,例如 vector<T> v4(n)
當(dāng)使用的模板是 int 時(shí),元素初值自動(dòng)設(shè)為0村怪。
;嘟健!注意使用花括號(hào)和圓括號(hào)甚负,這兩個(gè)影響非常大柬焕。花括號(hào)是進(jìn)行列表初始化梭域,圓括號(hào)是按提供的 (n, val) 來(lái)構(gòu)造 vector 對(duì)象斑举。
-
添加元素
push_back(..) 把元素添加到尾端
!病涨!注意富玷,雖然vector對(duì)象能高效增長(zhǎng),定義vector對(duì)象的時(shí)候設(shè)定其大小也就沒(méi)什么必要了没宾,但事實(shí)上這么做性能可能更差凌彬!
在創(chuàng)建vector時(shí),預(yù)先設(shè)定其容量是最好的循衰。
2病! 范圍for語(yǔ)句體內(nèi)不應(yīng)改變其所遍歷的序列的大小会钝,不能在里面對(duì)vector進(jìn)行添加元素等操作伐蒋。
-
對(duì)vector的操作
v.empty() v.size() // 返回vector中的元素個(gè)數(shù),size和empty操作和string類的一樣 v.push_back(t) v[n] v1 = v2 v1 = {a, b, c, ...} //同列表中的元素拷貝替換v1中的元素 v1 == v2 v1 != v2 <, <=, >, >= //按**字典序**進(jìn)行比較
size()
返回的是由 vector 定義的 size_type 類型迁酸,注意要使用vector<int>::size_type // 正確 vector::size_type // 錯(cuò)誤先鱼,要指定類型
只能對(duì)確知已存在的元素執(zhí)行下標(biāo)操作!
迭代器
所有標(biāo)準(zhǔn)庫(kù)容器都可以使用迭代器訪問(wèn)奸鬓,但是只有少數(shù)才同時(shí)支持下標(biāo)運(yùn)算符焙畔。string和vector都同時(shí)支持這兩種訪問(wèn)方式。
嚴(yán)格來(lái)講string不屬于容器類型串远,但是很多容器類型的操作string都支持宏多。
獲取迭代器使用 begin 和 end 成員。 其中 begin 指向第一個(gè)元素澡罚,end 表示尾元素的下一個(gè)元素的位置伸但,如果為空,則有 begin == end
留搔。 end 稱為尾后迭代器更胖,簡(jiǎn)稱尾迭代器。
-
迭代器的運(yùn)算符(類似于指針):
*iter iter->mem //解引用 iter 并獲取該元素的名為 mem 的成員,等價(jià)于 (*iter).mem ++iter --iter iter1 == iter2 iter1 != iter2
盡量習(xí)慣使用迭代器以及!=運(yùn)算符却妨,不是所有的標(biāo)準(zhǔn)庫(kù)容器都支持<運(yùn)算的饵逐,但是都支持迭代器和!=操作。
-
迭代器類型:
那些擁有迭代器的標(biāo)準(zhǔn)庫(kù)類型使用 iterator 和 const_iterator 來(lái)表示迭代器的類型管呵。
vector<int>::iterator it; string::iterator it2; vector<int>::const_iterator it3; // it3 只能讀取元素梳毙,不能寫元素 string::const_iterator it4; // it4 只能讀取元素,不能寫元素
const_iterator 類型和常量指針差不多捐下,能讀取但不能修改它所指的元素值。
如果 vector 對(duì)象或 string 對(duì)象是一個(gè)常量萌业,只能使用 const_iterator 坷襟。
!生年! 對(duì)于常量的容器類型婴程,begin 和 end 運(yùn)算符得到的是一個(gè) const_iterator ,要用對(duì)應(yīng)的 const_iterator 接住抱婉。如果一定要從非常量容器中得到常量迭代器档叔,可以使用
cbegin
和cend
這兩個(gè)運(yùn)算符。 -
箭頭運(yùn)算符 ->
it -> mem
的含義是(*it).mem
包含了對(duì) it 進(jìn)行解引用蒸绩,以及點(diǎn)運(yùn)算符衙四。例如一個(gè) vector<string> 類型的 text ,用迭代器訪問(wèn)遍歷 text患亿,直到遇到空白字符串為止:
for(auto it = text.cbegin(); it != text.cend() && !it -> empty(); ++it) cout << *it << endl;
其中
!it -> empty()
等價(jià)于!(*it).empty()
传蹈。先解引用得到 string 類型,再判斷這個(gè)字符串是否為空步藕。
5虢纭! 但凡使用了迭代器的循環(huán)體咙冗,都不要向迭代器所屬的容器添加元素沾歪。
-
string 和 vector 的迭代器的其他運(yùn)算
iter + n iter - n iter1 += n iter1 -= n iter1 - iter2 //相減得到迭代器之間的距離 >, >=, <, <=
也可以進(jìn)行一些算術(shù)運(yùn)算,例如得到中間元素:
auto mid = vi.begin() + vi.size() / 2;
這個(gè)距離是一個(gè) difference_type 雾消,帶符號(hào)整數(shù)灾搏,因?yàn)榫嚯x可正可負(fù)。
數(shù)組
數(shù)組的大小確定不變
數(shù)組的聲明形如 a[d]
仪或,其中a是數(shù)組名字确镊,d是數(shù)組維度,維度必須是一個(gè)常量表達(dá)式范删。不允許使用 auto 關(guān)鍵字蕾域,必須指定數(shù)組的類型。和vector一樣,數(shù)組的元素為對(duì)象旨巷,不存在引用的數(shù)組巨缘。
初始化數(shù)組時(shí)可以忽略維度,根據(jù)初始值數(shù)量計(jì)算并推測(cè)出維度采呐。
顯式初始化:
const unsigned sz = 3;
int ia1[sz] = {0, 1, 2};
int a2[] = {0, 1, 2};
int a3[5] = {0, 1, 2}; // 等價(jià)于 a3[5] = {0, 1, 2, 0, 0}
string a4[3] = {"hi", "bye"}; // 等價(jià)于 a4[3] = {"hi", "bye", ""}
int a5[2] = {0, 1, 2}; // 這句錯(cuò)誤若锁,初始值過(guò)多
對(duì)于字符數(shù)組,還可以用字符串來(lái)進(jìn)行初始化:
char a3[] = "c++"; // 等價(jià)于 char a3[] = {'c', '+', '+', '\0'}
8隆又固!注意這里有一個(gè) '\0' 結(jié)尾存放空字符,a3的實(shí)際大小為4煤率。
數(shù)組不允許拷貝和賦值 (也有一些編譯器能支持仰冠,但是最好不要使用這些非標(biāo)準(zhǔn)特性)
-
復(fù)雜數(shù)組的聲明
類型修飾符遵循從右向左結(jié)合的原則。
int *ptrs[10]; // ptrs是含有10個(gè)整型指針的數(shù)組 int &refs[10] = ...; // 錯(cuò)誤蝶糯,不存在引用的數(shù)組 int (*Parray)[10] = &arr; // Parray指向一個(gè)含有10個(gè)整數(shù)的數(shù)組 int (&arrRef)[10] = arr; // arrRef引用一個(gè)含有10個(gè)整數(shù)的數(shù)組
對(duì)于 ptrs洋只,首先[10],它是一個(gè)大小為10的數(shù)組昼捍,其次 * 表示它存放的是指針识虚,int 是存放的指針指向的類型;
對(duì)于 Parray妒茬,最好由內(nèi)向外地去理解它的含義担锤。圓括號(hào)內(nèi)的 *Parray 表示 Parray 是一個(gè)指針,接下來(lái)右邊的 [10] 可以知道 Parray 這個(gè)指針指向大小為 10 的數(shù)組郊闯,最左邊的 int 表示數(shù)組的數(shù)據(jù)類型妻献。
對(duì)于 arrRef,同理团赁,它是一個(gè)引用育拨,引用的內(nèi)容是一個(gè)含有10個(gè)整數(shù)的數(shù)組。
更復(fù)雜的:
int *(&arry)[10] = ptrs;
arry 是一個(gè)對(duì)數(shù)組的引用欢摄,引用的數(shù)組大小為10熬丧,存放的int類型的指針。
-
訪問(wèn)數(shù)組元素
下標(biāo)訪問(wèn)方式怀挠,數(shù)組的下標(biāo)是一個(gè)
size_t
類型析蝴,它是一種機(jī)器相關(guān)的無(wú)符號(hào)類型,足夠大以便能表示內(nèi)存中任意對(duì)象的大小绿淋。其他的下標(biāo)操作類似于 vector
-
指針和數(shù)組
使用數(shù)組的時(shí)候編譯器一般都會(huì)把它轉(zhuǎn)換成指針闷畸,可以用取地址符來(lái)得到指向數(shù)組元素的指針:
string nums[] = {"one", "two", "three"}; string *p = &nums[0]; // p 指向 nums 的第一個(gè)元素 string *p = nums; // 等價(jià)于上面一句
在大多數(shù)表達(dá)式中,使用數(shù)組類型的對(duì)象實(shí)際是使用一個(gè)指向該數(shù)組首元素的指針吞滞。
一般數(shù)組名 nums 都會(huì)被轉(zhuǎn)化成 &nums[0]佑菩,除了使用 decltype(nums) 的時(shí)候盾沫,會(huì)返回一個(gè) string[3] 類型。
對(duì)于空指針殿漠,允許給它加上或減去一個(gè)值為 0 的整型常量表達(dá)式赴精,兩個(gè)空指針也允許彼此相減,當(dāng)然結(jié)果為 0
-
標(biāo)準(zhǔn)庫(kù)函數(shù) begin 和 end
數(shù)組不是類型绞幌,因此 begin 和 end 不能作為成員函數(shù)蕾哟。使用方法:
int ia[] = {0,1,2,3,4,5,6,7,8,9}; int *beg = begin(ia); int *last = end(ia);
begin 函數(shù)返回指向 ia 首元素的指針, end 函數(shù)返回指向 ia 尾元素的下一位置的指針莲蜘。
!! 標(biāo)準(zhǔn)庫(kù)類型的下標(biāo)運(yùn)算符使用的索引值必須是無(wú)符號(hào)類型谭确,而內(nèi)置的下標(biāo)運(yùn)算符不同,可以是負(fù)值菇夸。例如:
int ia[] = {0, 2, 4, 5, 8};
int *p = &ia[2]; // p指向索引為2的元素
int i = *(p + 2);
int k = p[-2]; // k為ia[0]琼富,索引值可以為負(fù)
多維數(shù)組
多維數(shù)組 = 數(shù)組的數(shù)組..
定義一個(gè)數(shù)組元素任然為數(shù)組的數(shù)組時(shí),用兩個(gè)維度來(lái)定義它庄新,一個(gè)表示數(shù)組本身大小,一個(gè)表示其元素的大小薯鼠。
int ia[3][4]; // 大小為3的數(shù)組择诈,每個(gè)元素含有4個(gè)整數(shù)
int arr[10][20][30] = {0};
對(duì)于二維數(shù)組,第一個(gè)維度成為行出皇,第二個(gè)維度稱為列羞芍。
int ia[3][4] = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11} // 注意內(nèi)部是逗號(hào),括號(hào)都是花括號(hào)
};
也可以寫成一行的形式:
int ia[3][4] = {0, 1, 2, 3, 4, 5, 6,..., 11};
只初始化每一行的第一個(gè)元素:
int ia[3][4] = {{0}, {4}, {8}};
初始化第一行:
int ix[3][4] = {0, 3, 6, 9}; // 加不加花括號(hào)差別很大郊艘,對(duì)比上面一句
-
下標(biāo)引用
如果給出的下標(biāo)和維度一樣多荷科,那么就是這一點(diǎn)的元素值。如果缺少纱注,就是給定索引處的一個(gè)內(nèi)層數(shù)組畏浆。
int (&row)[4] = ia[1]; // row 是一個(gè)4個(gè)int的數(shù)組的一個(gè)引用,綁定 ia 的第二個(gè)4元數(shù)組上狞贱,也就是第二行刻获。
!瞎嬉! 對(duì)于
ia[1]
蝎毡,因?yàn)?ia 是一個(gè) int [3][4] 的類型,從左往右看氧枣,ia[1]應(yīng)該是一個(gè) int [4] 的類型沐兵,是一個(gè)四元數(shù)組。在使用范圍 for 語(yǔ)句處理二維數(shù)組時(shí)便监,對(duì)于外層數(shù)組一定要寫引用符號(hào)扎谎,否則無(wú)法通過(guò)編譯:
for(auto row : ia) for(auto col : row) //無(wú)法通過(guò)編譯 for(const auto &row : ia) for(auto col : row) //可以運(yùn)行
!! 除了最內(nèi)層循環(huán)外簿透,其他所有循環(huán)的控制變量都應(yīng)該是引用類型
-
指針和多維數(shù)組
由多維數(shù)組名轉(zhuǎn)化來(lái)的指針實(shí)際上是指向第一個(gè)內(nèi)層數(shù)組的指針移袍。
int ia[3][4]; int (*p)[4] = ia; // p 指向含有4個(gè)整數(shù)的數(shù)組 p = &ia[2]; // p 指向 ia 的尾元素
使用指針遍歷:
for(auto p = ia; p != ia + 3; ++p){ for(auto q = *p; q != *p + 4; ++q) cout << *q; cout << endl; } // 也可以更簡(jiǎn)潔: for(auto p = begin(ia); p != end(ia); ++p){ for(auto q = begin(*p); q != end(*p); ++q) cout << *q; cout << endl; } // 這里 auto 等價(jià)于 int[4] *
4.表達(dá)式
重載運(yùn)算符可以改變運(yùn)算對(duì)象的類型和返回值的類型,但是運(yùn)算對(duì)象的個(gè)數(shù)老充、運(yùn)算符的優(yōu)先級(jí)和結(jié)合律無(wú)法改變葡盗。
-
左值和右值
rvalue 和 lvalue
左值可以位于賦值語(yǔ)句的左側(cè),而右值不能啡浊。當(dāng)一個(gè)對(duì)象被用作右值的時(shí)候觅够,用的是對(duì)象的值(內(nèi)容);當(dāng)對(duì)象被用作左值的時(shí)候巷嚣,用的是對(duì)象的身份(在內(nèi)存中的位置)
在需要用右值的地方可以用左值代替喘先,但是不能把右值當(dāng)成左值使用。
- 賦值運(yùn)算符左側(cè)需要一個(gè)(非const)左值作為運(yùn)算對(duì)象廷粒,得到的結(jié)果仍然是一個(gè)左值窘拯。
- 取地址符作用于一個(gè)左值對(duì)象,返回一個(gè)指向該運(yùn)算對(duì)象的指針坝茎,這個(gè)指針是個(gè)右值涤姊。
-
求值順序
4種明確規(guī)定了運(yùn)算對(duì)象求值順序的運(yùn)算符:
- 邏輯與(&&) 先求左側(cè)運(yùn)算對(duì)象的值,只有左側(cè)運(yùn)算對(duì)象的值為真時(shí)才繼續(xù)求右側(cè)運(yùn)算對(duì)象的值
- 邏輯或(||) 先求左側(cè)嗤放,左側(cè)為假時(shí)才求右側(cè)表達(dá)式
- 條件運(yùn)算符(?:)
- 逗號(hào)運(yùn)算符(,)
算術(shù)運(yùn)算符
一元正負(fù)號(hào)具有最高優(yōu)先級(jí)思喊,其次* / %,最低的是+ -,.
c++11中次酌,除了 -m 導(dǎo)致溢出的情況恨课,其他時(shí)候都有 (-m)/n 和 m/(-n) 都等于 -(m/n),m%(-n) 等于 m%n岳服, (-m)%n 等于 -m%n
也就是: (-21)%(-8) = (-21)%8 = -21%8 = -5
邏輯運(yùn)算符
邏輯與和邏輯或都遵循先計(jì)算左側(cè)表達(dá)式的原則(短路求值)剂公。他們的左側(cè)運(yùn)算對(duì)象一般用來(lái)保證右側(cè)求值過(guò)程中的正確性和安全性,例如:
index != s.size() && !isspace(s[index])
s.empty() || s[s.size() - 1] == '.' // 遇到空字符串或以句號(hào)結(jié)束的字符串
!!在進(jìn)行比較運(yùn)算時(shí)除非比較的對(duì)象是布爾類型派阱,否則就不要用布爾類型的字面值 true 和 false 作為運(yùn)算對(duì)象诬留。
賦值運(yùn)算符
賦值運(yùn)算符的優(yōu)先級(jí)比較低,在表達(dá)式中盡量加上括號(hào)贫母。
允許使用花括號(hào)括起來(lái)的初始值列表作為賦值語(yǔ)句的右側(cè)運(yùn)算對(duì)象:
int k = {3.14}; // 錯(cuò)誤文兑,進(jìn)行了窄化轉(zhuǎn)換
vector<int> vi = {0,1,2,3,4}; // 正確, vi 包含 5 個(gè)元素
賦值語(yǔ)句滿足右結(jié)合律,賦值語(yǔ)句返回的是左側(cè)運(yùn)算對(duì)象:
int ival, jval;
ival = jval = 0; // 都被初始化為0
其他復(fù)合賦值運(yùn)算符:(都等價(jià)于a = a op b)
+= -= *= /= %=
<<= >>= &= ^= |=
遞增和遞減運(yùn)算符
++和--有前置和后置之分腺劣。
int j, i = 0;
j = i++; // 后置版本得到遞增之前的值绿贞, j=0, i=1
j = ++i; // 前置版本得到遞增之后的值, j=2, i=2
前置版本將對(duì)象本身作為左值返回橘原,后置版本則將對(duì)象原始值的副本作為右值返回籍铁。
!! 除非必須涡上,否則不用后置版本的遞增遞減運(yùn)算符。因?yàn)楹笾冒姹就瑫r(shí)存儲(chǔ)了修改前后的兩個(gè)值拒名,如果不需要用修改前的值的話吩愧,后置的遞增、遞減就造成一種浪費(fèi)增显。
后置的++也可以用來(lái)輸出前一個(gè)元素雁佳,例如循環(huán)輸出一個(gè)vector對(duì)象內(nèi)容直至遇到(但不包括)第一個(gè)負(fù)值為止:
auto pbeg = v.begin();
while(pbeg != v.end() && *beg >= 0)
cout << *pbeg++; // 后置++,每次解引用輸出的都是迭代器的前一個(gè)
++ 的優(yōu)先級(jí)比解引用 * 高同云,因此 *pbeg++ 等價(jià)于 *(pbeg++)
后置的 ++ 操作返回值是未自增前的那個(gè) pbeg糖权,因此 pbeg 自增后,解引用的仍然是原來(lái)沒(méi)自增的那個(gè)迭代器炸站。
P前摹!注意 *pbeg++
這種寫法旱易,常用禁偎。
成員訪問(wèn)運(yùn)算符
ptr->mem
等價(jià)于 (*ptr).mem
解引用運(yùn)算符的優(yōu)先級(jí)低于點(diǎn)運(yùn)算符!所以上式必須加括號(hào)阀坏。
箭頭運(yùn)算符作用于一個(gè)指針類型的運(yùn)算對(duì)象届垫,結(jié)果是一個(gè)左值。點(diǎn)運(yùn)算符的結(jié)果則根據(jù)成員所屬的對(duì)象是左值和右值而定全释。
條件運(yùn)算符
簡(jiǎn)單的 if-else 語(yǔ)句可以用條件運(yùn)算符(?:)實(shí)現(xiàn)
條件運(yùn)算符可以嵌套:
finalgrade = (grade > 90) ? "high pass"
: (grade < 60) ? "fail" : "pass";
最好不要嵌套太多層。
N笳浸船!在輸出表達(dá)式中,由于條件運(yùn)算符的優(yōu)先級(jí)非常低寝蹈,因此兩邊一般要加上括號(hào)李命。
cout<< ((grade < 60) ? "fail" : "pass") <<endl;
位運(yùn)算符
運(yùn)算符 | 功能 |
---|---|
~ | 位求反 |
<< | 左移 |
>> | 右移 |
& | 位與 |
^ | 位異或 |
| | 位或 |
!箫老!對(duì)符號(hào)位的處理沒(méi)有規(guī)定封字,因此強(qiáng)烈建議僅對(duì)無(wú)符號(hào)類型進(jìn)行位運(yùn)算
sizeof運(yùn)算符
兩種形式:
sizeof(type)
sizeof expr
sizeof 滿足右結(jié)合律,且優(yōu)先級(jí)和 * 一樣耍鬓。有 sizeof *p 也就是 sizeof(*p)阔籽。
因?yàn)閟izeof實(shí)際不會(huì)去求表達(dá)式的值,所以即使 p 是一個(gè)無(wú)效(未初始化)指針也無(wú)所謂牲蜀。
- 對(duì) char 類型或者類型為 char 的表達(dá)式執(zhí)行 sizeof 運(yùn)算笆制,結(jié)果得 1
- 對(duì)引用類型執(zhí)行 sizeof 運(yùn)算,得到被引用對(duì)象所占空間的大小
- 對(duì)指針執(zhí)行 sizeof 運(yùn)算涣达,得到指針本身所占空間大小
- 對(duì)解引用指針執(zhí)行 sizeof 運(yùn)算在辆,得到指針指向的對(duì)象所占空間的大小证薇,指針不需要有效
- 對(duì)數(shù)組執(zhí)行 sizeof,得到整個(gè)數(shù)組所占空間的大小匆篓,sizeof不會(huì)把數(shù)組轉(zhuǎn)化為指針處理
- 對(duì) string 對(duì)象或 vector 對(duì)象運(yùn)算只返回該類型固定部分的大小浑度,不會(huì)計(jì)算對(duì)象中的元素占用了多少空間
類型轉(zhuǎn)換
如果兩種類型可以相互轉(zhuǎn)換,那么他們就是關(guān)聯(lián)的鸦概。
-
隱式轉(zhuǎn)換:
- 在大多數(shù)表達(dá)式中箩张,比 int 類型小的整型值首先提升為較大的整數(shù)類型
- 在條件中,非布爾值轉(zhuǎn)換成布爾值
- 初始化過(guò)程中完残,初始值轉(zhuǎn)化成變量的類型咖城;賦值語(yǔ)句中抒钱,右側(cè)的對(duì)象類型轉(zhuǎn)換成左側(cè)的
- 算術(shù)運(yùn)算和關(guān)系運(yùn)算中,多種類型都轉(zhuǎn)換成同一種類型
- 函數(shù)調(diào)用也會(huì)發(fā)生類型轉(zhuǎn)換
- 數(shù)組轉(zhuǎn)換成指針,但是在 &梦皮、sizeof、decltype下不會(huì)轉(zhuǎn)化
-
整型提升:
負(fù)責(zé)把小整數(shù)類型轉(zhuǎn)換成較大的整數(shù)類型腌歉。對(duì)于bool稽鞭、char、signed char二蓝、unsigned char誉券、short和unsigned short,只要他們所有可能的值都能存在 int 里刊愚,他們就會(huì)被提升成 int 類型踊跟。
較大的 char 類型(wchar_t、char16_t鸥诽、char32_t)提升成int商玫、unsigned int、long牡借、unsigned long拳昌、long long和unsigned long long 中最小的一種類型。
在計(jì)算時(shí)钠龙,首先進(jìn)行整型提升炬藤,如果類型匹配則進(jìn)行計(jì)算,如果提升后的兩個(gè)運(yùn)算對(duì)象一個(gè)帶符號(hào)一個(gè)無(wú)符號(hào)碴里,且無(wú)符號(hào)類型不小于帶符號(hào)的沈矿,則帶符號(hào)的會(huì)被轉(zhuǎn)化成無(wú)符號(hào)的,例如unsigned int 和 int 會(huì)使 int 轉(zhuǎn)化成無(wú)符號(hào)的并闲。
-
顯示轉(zhuǎn)換:
一個(gè)命名的強(qiáng)制類型轉(zhuǎn)換具有如下形式:
cast-name<type>(expression);
cast-name有四種:
-
static_cast: 任何不包含底層const的都可以使用
double slope = static_cast<double>(j) / i;
-
const_cast: 只能改變運(yùn)算對(duì)象的底層const细睡,“去掉const性質(zhì)”,一般用于有函數(shù)重載的上下文中
const char *pc; char *p = const_cast<char*>(pc); // 正確帝火,但是不能通過(guò) p 寫值
dynamic_cast
reinterpret_cast:通常為運(yùn)算對(duì)象的位模式提供較低層次上的重新解釋
A镝恪湃缎!盡量不要使用強(qiáng)制類型轉(zhuǎn)換
-
5.語(yǔ)句
-
空語(yǔ)句:只包含一個(gè)單獨(dú)的分號(hào),最好加上注釋
也可以寫一個(gè)空塊:
while(cin >> s && s != sought) { } // 空塊 while(cin >> s && s != sought) ; // 空語(yǔ)句
-
懸垂 else :
當(dāng)一個(gè)if語(yǔ)句嵌套在另一個(gè)if語(yǔ)句中時(shí)蠢壹,可能if分支會(huì)多于else分支嗓违。c++規(guī)定else與離它最近的尚未匹配的if匹配,這點(diǎn)和python不同图贸!
最好用花括號(hào)控制執(zhí)行路徑:
if(grade % 10 >= 3) { // 花括號(hào)必不可少蹂季! if(grade % 10 > 7) lettergrade += '+'; } else lettergrade += '-';
-
switch 語(yǔ)句:
switch (ch) { case 'a': ++aCnt; break; case 'b': ++bCnt; break; ... default: ++otherCnt; break; }
如果某個(gè) case 標(biāo)簽匹配成功,將從該標(biāo)簽往后順序執(zhí)行所有 case 分支疏日,如果不 break偿洁,直到 switch 結(jié)束時(shí)才會(huì)停下來(lái)。
或者把他們都寫在一行里也是一種合法的語(yǔ)句沟优。
switch (ch) { // 只要是5個(gè)字母中的任意一個(gè)都會(huì)執(zhí)行后面的++ case 'a': case 'e': case 'i': case 'o': case 'u': ++vowelCnt; break; } switch (ch) { case 'a': case 'e': case 'i': case 'o': case 'u': ++vowelCnt; break; } // 一般不要省略分支后面的break語(yǔ)句涕滋,如果要省略,最好加上注釋挠阁!
如果需要為某個(gè) case 分支定義并初始化一個(gè)變量宾肺,應(yīng)該把變量定義在塊內(nèi),加上一個(gè) { }
-
跳轉(zhuǎn)語(yǔ)句
break 語(yǔ)句負(fù)責(zé)終止離他最近的 while侵俗、 do while锨用、 for 或 switch 語(yǔ)句。僅限于最近的一個(gè)循環(huán)或者 switch隘谣,只跳出一層循環(huán)增拥。
continue 語(yǔ)句終止最近的循環(huán)的當(dāng)前迭代,并立即開(kāi)始下一次循環(huán)寻歧。
-
try 語(yǔ)句塊
異常處理包括: throw 表達(dá)式跪者,引發(fā)異常; try 語(yǔ)句塊熄求,處理異常,以關(guān)鍵字 try 開(kāi)始逗概,以一個(gè)或多個(gè) catch 子句結(jié)束弟晚,稱為異常處理代碼;一套異常類逾苫,用于在 throw 表達(dá)式和相關(guān)的 catch 子句之間傳遞異常的具體信息卿城。
拋出異常:
if(item1.isbn() != item2.isbn()) throw runtime_error("Data must refer to same ISBN"); cout << item1 + item2 <<endl;
異常處理代碼:
try { ... if(item1.isbn() != item2.isbn()) throw runtime_error("Data must refer to same ISBN"); ... } catch(runtime_error err) { cout << err.what() << "\nTry again? Enter y or n: " <<endl; char c; cin >> c; if(!cin || c == 'n') break; }
一個(gè) try 語(yǔ)句塊拋出多個(gè)異常,后面接多個(gè) catch 子句進(jìn)行處理
標(biāo)準(zhǔn)異常:<stdexcept>定義的異常類
exception 最常見(jiàn)的問(wèn)題 runtime_error 只有在運(yùn)行時(shí)才能檢測(cè)出的問(wèn)題 range_error 運(yùn)行時(shí)錯(cuò)誤:結(jié)果超出了有意義的值域范圍 overflow_error 運(yùn)行時(shí)錯(cuò)誤:計(jì)算上溢 underflow_error 運(yùn)行時(shí)錯(cuò)誤:計(jì)算下溢 logic_error 程序邏輯錯(cuò)誤 domain_error 邏輯錯(cuò)誤:參數(shù)對(duì)應(yīng)的結(jié)果值不存在 invaild_argument 邏輯錯(cuò)誤:無(wú)效參數(shù) length_error 邏輯錯(cuò)誤:試圖創(chuàng)建一個(gè)超出該類型最大長(zhǎng)度的對(duì)象 out_of_range 邏輯錯(cuò)誤:使用一個(gè)超出有效范圍的值