最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

C++ Primer 筆記-第6章 函數(shù)

2022-12-03 19:18 作者:Code有毒  | 我要投稿

6.1 函數(shù)基礎(chǔ)

  1. 函數(shù)的本質(zhì)是一個(gè)命名了的代碼塊。

  2. 函數(shù)的返回值不能是數(shù)組類型或函數(shù)類型,但可以是指向數(shù)組的或函數(shù)的指針。

6.1.1 局部對(duì)象

  1. 我們把只存在于塊執(zhí)行期間的對(duì)象成為?自動(dòng)對(duì)象。

  2. 局部靜態(tài)對(duì)象 local static object?在程序的執(zhí)行路徑第一次經(jīng)過(guò)對(duì)象定義語(yǔ)句時(shí)初始化,并且直到程序終止才被銷毀,在此期間即使對(duì)象所在的函數(shù)結(jié)束執(zhí)行也不會(huì)對(duì)它有影響。

6.1.2 函數(shù)聲明

  1. 函數(shù)只能定義一次,但是可以聲明多次。

6.2 參數(shù)傳遞

6.2.1 傳值參數(shù)

  1. 熟悉 C 的程序員常常使用指針類型的形參訪問(wèn)函數(shù)外部對(duì)象。在 C++ 語(yǔ)言中,建議使用引用類型的形參替代指針。

6.2.3?const?形參和實(shí)參

  1. 和其他初始化過(guò)程一樣,當(dāng)用實(shí)參初始化形參時(shí)會(huì)忽略掉頂層?const。

  2. 因?yàn)轫攲?const?被忽略掉,所以傳入兩個(gè)?fcn()?的參數(shù)可以完全一樣,造成函數(shù)重載錯(cuò)誤:

void fcn(const int i){}

void fcn(int i){} ? ? ? ? ?// 錯(cuò)誤:重復(fù)定義

6.2.4 數(shù)組形參

  1. 管理指針形參有三種常用的技術(shù):

    (1) 使用編輯指定數(shù)組長(zhǎng)度:要求數(shù)組本身包含一個(gè)結(jié)束標(biāo)記。

    (2) 使用標(biāo)準(zhǔn)庫(kù)規(guī)范:傳遞指向數(shù)組首元素和尾后元素的指針。

    (3) 顯示傳遞一個(gè)表示數(shù)組大小的形參。

  2. 形參可以是數(shù)組的引用,且?&arr?兩端的括號(hào)不能少:

void f(int (&arr)[10]){} ? ?// 正確:arr是具有10個(gè)整數(shù)的整型數(shù)組的引用

void f(int &arr[10]){} ? ? ?// 錯(cuò)誤:將arr聲明成了引用的數(shù)組

  1. 傳遞多維數(shù)組:

// matrix 指向數(shù)組的首元素,該數(shù)組的元素是由10個(gè)整數(shù)構(gòu)成的數(shù)組

void f(int (*matrix)[10], int rowsize){}


// 再次強(qiáng)調(diào),*matrix兩端的括號(hào)必不可少:

int *matrix[10]; ? ? ? ? ? // 10個(gè)指針構(gòu)成的數(shù)組

int (*matrix)[10]; ? ? ? ? // 指向含有10個(gè)整數(shù)的數(shù)組的指針

6.2.5?main: 處理命令行選項(xiàng)

  1. 第二個(gè)形參?argv?是一個(gè)數(shù)組,它的元素是指向 C 風(fēng)格的字符串的指針。

// 兩個(gè)表達(dá)式等價(jià)

int main(int argc, char *argv[]){}

int main(int argc, char **argc){}

  1. 假定?main?函數(shù)位于執(zhí)行文件 prog 之內(nèi),可以向程序傳遞選項(xiàng):prog -d -o ofile data0?,此時(shí)?argc?等于5,argv?應(yīng)該包含如下的C風(fēng)格字符串:

argc[0] = "prog"; ? ? ? ? ?// 或者 argv[0] 也可以指向一個(gè)空字符串

argc[1] = "-d";

argc[2] = "-o";

argc[3] = "ofile";

argc[4] = "data0";

argc[5] = 0;

  1. 當(dāng)使用?argv?中的實(shí)參時(shí),一定要記得可選的實(shí)參從?argv[1]?開(kāi)始;argv[0]?保存程序的名字,而非用戶輸入。

6.2.6 含有可變形參的函數(shù)

  1. 為了編寫(xiě)處理不同數(shù)量實(shí)參的函數(shù),c++11新標(biāo)準(zhǔn)提供了兩種主要的辦法:如果所有的實(shí)參函數(shù)類型相同,可以傳遞一個(gè)名為?initializer_list?的標(biāo)準(zhǔn)庫(kù)函數(shù);如果實(shí)參的類型不同,我們可以使用可變參數(shù)模板。

  2. 拷貝或賦值一個(gè)?initializer_list?對(duì)象不會(huì)拷貝列表中的元素,拷貝后原始列表和副本共享元素。

  3. 和?vector?不同,initializer_list?對(duì)象中的元素永遠(yuǎn)是常量值,我們無(wú)法改變?initializer_list?對(duì)象中元素的值。

  4. 省略符形參是為了便于 C++ 程序訪問(wèn)某些特殊的 C 代碼而設(shè)置的,這些代碼用到了名為?varargs?的 C 標(biāo)準(zhǔn)庫(kù)功能。省略符形參僅僅用于 C 和 C++ 通用的類型,大多數(shù)類類型的對(duì)象在傳遞給省略符形參時(shí)無(wú)法正確拷貝。

  5. 省略符形參只能出現(xiàn)列表的最后一個(gè)位置,省略符對(duì)應(yīng)的實(shí)參無(wú)需類型檢查:

void foo(parm_list, ...);

void foo(...);

6.3 返回類型和?return?語(yǔ)句

6.3.2 有返回值函數(shù)

  1. 函數(shù)的返回類型決定函數(shù)調(diào)用是否是左值,調(diào)用一個(gè)返回引用的函數(shù)得到左值,其他返回類型得到右值。

  2. 允許?main?函數(shù)沒(méi)有?return?語(yǔ)句直接結(jié)束。編譯器會(huì)隱式地插入一條返回 0 的?return?語(yǔ)句。

  3. 為了使?main?函數(shù)返回的值與機(jī)器無(wú)關(guān),cstdlib?頭文件定義了兩個(gè)預(yù)處理變量:EXIT_FAILURS?和?EXIT_SUCCESS。

  4. main?函數(shù)不能遞歸調(diào)用自身

6.3.3 返回?cái)?shù)組指針

  1. 因?yàn)閿?shù)組不能被拷貝,所以函數(shù)不能返回?cái)?shù)組。不過(guò),函數(shù)可以返回?cái)?shù)組的指針或引用:

// 使用類型別名

typedef int arrT[10]; ?// arrT是一個(gè)類型別名,它表示的類型是含有10個(gè)整數(shù)的數(shù)組

using arrT = int[10]; ?// arrT的等價(jià)聲明

arrT* func(int i); ? ? // func返回一個(gè)指向含有10個(gè)整數(shù)的數(shù)組的指針


// 不使用類型別名

Type (*function(parameter_list))[dimension];// 數(shù)組的維度必須跟在函數(shù)名字之后

//例如:

int (*func(int i))[10];


// 使用尾置返回類型

auto func(int i) -> int(*)[10];


// 如果知道函數(shù)返回的指針將指向哪個(gè)數(shù)組,可以使用 decltype 關(guān)鍵字聲明返回類型。

int odd[] = {1, 2, 3};

decltype(odd) *arrPtr(int i)

{ ?

? ?return &odd;

}


6.4 函數(shù)重載

  1. 重載的前提是要在同一個(gè)作用域下。

  2. main?函數(shù)不能重載。

// 一個(gè)擁有頂層 `const` 的形參無(wú)法和另一個(gè)沒(méi)有頂層 `const` 的形參區(qū)分開(kāi)來(lái):

int func(double* a);

int func(double* const a);


// 底層const形參可以區(qū)分

int func(double* b);

int func(const double* b);

  1. 調(diào)用重載函數(shù)時(shí),如有多于一個(gè)函數(shù)可以匹配,但是每一個(gè)都不是明顯的最佳選擇。此時(shí)也將發(fā)生錯(cuò)誤,稱為?二義性調(diào)用 ambiguous call。

6.4.1 重載與作用域

  1. 如果我們?cè)趦?nèi)層作用域中聲明了名字,它將隱藏外層作用域中聲明的同名實(shí)體。在不同的作用域中無(wú)法重載函數(shù)名。

6.5 特殊用途語(yǔ)言特性

6.5.1 默認(rèn)實(shí)參

  1. 要注意由于隱式類型轉(zhuǎn)換而出現(xiàn)的與預(yù)期不符合的函數(shù)調(diào)用情況。

  2. 在給定的作用域中一個(gè)形參只能被賦予一次默認(rèn)實(shí)參,函數(shù)的后續(xù)聲明只能為之前那些沒(méi)有默認(rèn)值的形參添加默認(rèn)實(shí)參,而且該形參右側(cè)的所有形參必須都有默認(rèn)值。

6.5.2 內(nèi)聯(lián)函數(shù)和?constexpr?函數(shù)

  1. 一次函數(shù)的調(diào)用包含的工作:調(diào)用前要先保存寄存器,并在返回時(shí)恢復(fù);可能需要拷貝實(shí)參;程序轉(zhuǎn)向一個(gè)新的位置繼續(xù)執(zhí)行。

  2. 內(nèi)聯(lián)函數(shù)可以避免函數(shù)調(diào)用的開(kāi)銷,在調(diào)用點(diǎn)上 “內(nèi)聯(lián)地” 展開(kāi)。

  3. constexpr?函數(shù)是指能用于常量表達(dá)式的函數(shù)。函數(shù)的返回類型及所有形參的類型都得是字面值類型,而且函數(shù)體中必須有且只有一條?return?語(yǔ)句。編譯器會(huì)把對(duì)?constexpr?函數(shù)的調(diào)用替換成其結(jié)果值。為了能在編譯過(guò)程中隨視展開(kāi),constexpr?函數(shù)被隱式地指定為內(nèi)聯(lián)函數(shù)。

  4. 內(nèi)聯(lián)函數(shù)和?constexpr函數(shù)通常定義在頭文件中。

6.5.3 調(diào)試幫助

  1. assert是一種預(yù)處理宏,常用于檢查“不能發(fā)生”的條件。

  2. assert?的行為依賴于一個(gè)名為?NDEBUG?的預(yù)處理變量的狀態(tài)。如果定義了?NDEBUG,則?assert?什么也不做。

  3. 應(yīng)該把?assert?當(dāng)作調(diào)試程序的一種輔助手段,但是不能用它替代真正的運(yùn)行時(shí)邏輯檢查,也不能替代程序本身應(yīng)該包含的錯(cuò)誤檢查。

  4. 編譯器定義了5個(gè)對(duì)程序調(diào)試很有用的局部靜態(tài)變量:

_ _func_ _ 存放函數(shù)名的字符串字面值

_ _FILE_ _ 存放文件名的字符串字面值

_ _LINE_ _ 存放當(dāng)前行號(hào)的整型字面值

_ _TIME_ _ 存放文件編譯時(shí)間的字符串字面值

_ _DATE_ _ 存放文件編譯日期的字符串字面值


6.6 函數(shù)匹配

  1. 函數(shù)匹配的第一步是選定本次調(diào)用對(duì)應(yīng)的重載函數(shù)集,集合中的函數(shù)稱為?候選函數(shù) candidate function。

  2. 函數(shù)匹配的第二步考察本次調(diào)用提供的實(shí)參,然后從候選函數(shù)中選出能被這組實(shí)參調(diào)用的函數(shù),這些新選出的函數(shù)稱為?可行函數(shù) viable fuction。

  3. 函數(shù)匹配的第三步是從可行函數(shù)中選擇與本次調(diào)用最匹配的函數(shù)。

  4. 含有多個(gè)形參的函數(shù)匹配規(guī)則:

    ·該函數(shù)每個(gè)實(shí)參的匹配都不劣與其他可行函數(shù)需要的匹配

    ·至少有一個(gè)實(shí)參的匹配優(yōu)于其他可行函數(shù)提供的匹配。

    ·如果在檢查了所有實(shí)參之后沒(méi)有任何一個(gè)函數(shù)脫穎而出,則該調(diào)用是錯(cuò)誤的。編譯器將報(bào)告二義性調(diào)用的信息。

  5. 調(diào)用重載函數(shù)時(shí)應(yīng)盡量避免強(qiáng)制類型轉(zhuǎn)換。如果在實(shí)際應(yīng)用中確實(shí)需要強(qiáng)制類型轉(zhuǎn)換,則說(shuō)明我們?cè)O(shè)計(jì)的形參集合不合理。

6.6.1 實(shí)參類型轉(zhuǎn)換

  1. 為了確定最佳匹配,編譯器將實(shí)參類型到形參類型的轉(zhuǎn)換劃分了成了幾個(gè)等級(jí):

    (1) 精確匹配:

    ·實(shí)參類型?和?形參類型?相同。

    ·實(shí)參從?數(shù)組類型?或?函數(shù)類型?轉(zhuǎn)換成對(duì)應(yīng)的指針類型。

    · 向?qū)崊⑻砑禹攲?const?或者從實(shí)參中刪除頂層?const。

    (2) 通過(guò)?const?轉(zhuǎn)換?實(shí)現(xiàn)的匹配。

    (3) 通過(guò)?類型提升?實(shí)現(xiàn)的匹配。

    (4) 通過(guò)?算術(shù)類型轉(zhuǎn)換?或?指針轉(zhuǎn)換?實(shí)現(xiàn)的匹配。

    (5) 通過(guò)?類類型轉(zhuǎn)換?實(shí)現(xiàn)的匹配。

6.7 函數(shù)指針

  1. 函數(shù)指針指向的是?函數(shù)?而非?對(duì)象?。函數(shù)指針指向某種特定的類型。函數(shù)的類型由它的返回類型和形參類型共同決定,與函數(shù)名無(wú)關(guān)。

// 函數(shù)聲明:

bool func(int a);


/ 函數(shù)指針:

bool (*pf)(int); ? ? ? ? ?//未初始化

// *pf兩端的括號(hào)必不可少

bool *pf(int); ? ? ? ? ? ?// 聲明了一個(gè)名為pf的函數(shù),該函數(shù)返回bool*

  1. 當(dāng)我們把函數(shù)名作為值使用時(shí),該函數(shù)自動(dòng)地轉(zhuǎn)換成指針。

pf = func; pf = &func; ? ?// 等價(jià)

  1. 直接使用指向函數(shù)的指針調(diào)用該函數(shù),無(wú)需提前解引用指針:

bool b1 = pf(1); ? ? ? ? ?// 調(diào)用func()

bool b2 = (*pf)(1); ? ? ? // 等價(jià)調(diào)用

bool b3 = func(1); ? ? ? ?// 等價(jià)調(diào)用

  1. 在指向不同函數(shù)類型的指針間不存在轉(zhuǎn)換規(guī)則。可以給函數(shù)值賦值一個(gè)?nullptr?或值為 0 的整型常量表達(dá)式,表示該指針沒(méi)有指向任何一個(gè)函數(shù)。

  2. 如果定義了指向重載函數(shù)的指針,編譯器通過(guò)指針類型決定選用哪個(gè)函數(shù),指針類型必須與重載函數(shù)中的某一個(gè)精確匹配。

  3. 和數(shù)組類似,不能定義函數(shù)類型的形參,但是形參可以是指向函數(shù)的指針。

void use(bool pf(int)); ? // 形參是函數(shù)類型,會(huì)自動(dòng)轉(zhuǎn)換成指向函數(shù)的指針void use(bool (*pf)(int)); ? ? // 等價(jià)的聲明,顯示地將形參定義成指向函數(shù)的指針

  1. 直接使用函數(shù)指針類型顯得冗長(zhǎng)而煩瑣。類型別名?typedef?和?decltype?能簡(jiǎn)化使用函數(shù)指針的代碼。下面的四個(gè)聲明語(yǔ)句聲明的是同一個(gè)函數(shù),編譯器會(huì)自動(dòng)將函數(shù)類型轉(zhuǎn)換成指針。

bool func(int a);

// Func 和 Func2是函數(shù)類型

typedef bool Func(int);

typedef decltype(func) Func2; ? ?// 等價(jià)

void use(Func); ? ? ? ? ? ? ? ? ?// 聲明1

void use(Func2); ? ? ? ? ? ? ? ? // 聲明2


// FuncP 和 FuncP2 是指向函數(shù)的指針

typedef bool (*Funcp)(int);

typedef decltype(func) *Funcp2; ?// 等價(jià)

void use(Funcp); ? ? ? ? ? ? ? ? // 聲明3v

oid use(Funcp2); ? ? ? ? ? ? ? ? // 聲明4

  1. 與函數(shù)不能直接返回?數(shù)組?但能返回?指向數(shù)組的指針?類似,函數(shù)不能直接返回?函數(shù)類型?但能返回?指向函數(shù)的指針。

  2. 必須把返回類型寫(xiě)成?指針?形式,編譯器?不會(huì)自動(dòng)地?將函數(shù)返回類型當(dāng)成對(duì)應(yīng)的指針類型處理。

// 使用類型別名聲明f1:

using F = int(int*, int); ? ? ? ?// F是函數(shù)類型,不是指針

using PF = int(*)(int*, int); ? ?// PF是指針類型

PF f1(int); ? ? ? ? ? ? ? ? ?// 正確:PF是指向函數(shù)的指針,f1返回指向函數(shù)的指針

F *f1(int); ? ? ? ? ? ? ? ? ?// 正確:顯示地指定返回類型是指向函數(shù)的指針F

f1(int); ? ? ? ? ? ? ? ? ? ? // 錯(cuò)誤:F是函數(shù)類型,f1不能返回一個(gè)函數(shù)


// 直接聲明f1:

int (*f1(int))(int*, int);


// 使用尾后返回類型聲明f1:

auto f1(int) -> int(*)(int*, int);


// 如果明確知道返回函數(shù)是哪一個(gè),就能使用 decltype 簡(jiǎn)化書(shū)寫(xiě)

// decltype返回的是函數(shù)類型而非指針,所以需要顯式地加上*以表明需要返回的是指針而非函數(shù)本身

bool func(int);

decltype(func) *getFcn(const string&);



C++ Primer 筆記-第6章 函數(shù)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
华池县| 锦州市| 西充县| 镶黄旗| 襄城县| 定州市| 闽侯县| 澳门| 建平县| 仙游县| 南乐县| 西丰县| 泸水县| 浦北县| 霍山县| 兴业县| 潼南县| 綦江县| 临沂市| 工布江达县| 镇安县| 合江县| 安多县| 古浪县| 紫云| 汤原县| 汝城县| 青铜峡市| 肃北| 永靖县| 马鞍山市| 和静县| 方城县| 永城市| 政和县| 商城县| 西乌| 富源县| 五河县| 宜兴市| 贞丰县|