C++學(xué)習(xí)筆記——函數(shù)

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

  1. 函數(shù)定義:返回類型削解、函數(shù)名富弦、0個(gè)或多個(gè)形參組成的列表、函數(shù)體氛驮。
    • 形參以逗號隔開腕柜。
    • 形參列表位于一對圓括號內(nèi)。
  2. 函數(shù)執(zhí)行:調(diào)用運(yùn)算符矫废。
    • 調(diào)用運(yùn)算符作用于函數(shù)或指向函數(shù)的指針盏缤。
    • 圓括號內(nèi)為一個(gè)用逗號隔開的實(shí)參列表,用于對形參進(jìn)行初始化蓖扑。
    • 調(diào)用表達(dá)式的類型即為函數(shù)的返回類型唉铜。
  3. 函數(shù)調(diào)用過程中,完成兩項(xiàng)工作:
    • 用實(shí)參初始化對應(yīng)的形參律杠。
    • 將程序控制權(quán)轉(zhuǎn)移給被調(diào)用函數(shù)潭流。
  4. 形參與實(shí)參:
    • 實(shí)參的求值順序未被規(guī)定竞惋。
    • 初始化過程中,實(shí)參應(yīng)與形參類型關(guān)聯(lián)灰嫉。
  5. 函數(shù)的形參列表:
    • 形參列表可為空拆宛。
    • 任意兩個(gè)形參不可同名,且不能與函數(shù)最外層作用域中的局部變量同名熬甫。
    • 形參可以不命名胰挑,用來表示該形參在函數(shù)中不被使用,但此操作不影響實(shí)參個(gè)數(shù)椿肩。
  6. 函數(shù)的返回值:
    • 可為void瞻颂。
    • 不可以是數(shù)組或函數(shù),但可以是指向數(shù)組和指向函數(shù)的指針郑象。
  7. 局部靜態(tài)對象:在程序的執(zhí)行路徑第一次經(jīng)過對象定義語句時(shí)初始化贡这,直到程序終止時(shí)被銷毀。
    • 在類型聲明前使用static關(guān)鍵字厂榛。
    • 局部靜態(tài)變量沒有顯式的初始值時(shí)盖矫,初始化為0。
  8. 函數(shù)聲明:可以聲明多次击奶,但只能定義一次辈双。
    • 函數(shù)聲明應(yīng)該在頭文件中,且源文件應(yīng)包含頭文件柜砾。

參數(shù)傳遞

  1. 調(diào)用類型:根據(jù)形參是否為引用分為引用傳遞(傳引用調(diào)用)和值傳遞(傳值調(diào)用)湃望。
  2. 參數(shù)類型:
    • 傳值參數(shù):初始值被拷貝給變量,此時(shí)對變量的改動(dòng)不會(huì)影響初始值痰驱。
    • 指針形參:可以通過指針間接訪問其所指的對象证芭。
    • 傳引用參數(shù):形參與實(shí)參綁定,函數(shù)可以通過改變形參來間接改變實(shí)參担映。
    • 使用引用废士,避免拷貝,更加高效蝇完。(無需修改參數(shù)時(shí)官硝,使用常量引用)
    • 使用引用參數(shù)可以返回額外信息。
  3. const類型的形參與實(shí)參:實(shí)參初始化形參時(shí)會(huì)忽略頂層const限制短蜕。
//需要注意:
void func(const int i);  //func能夠讀取i泛源,但不能向i寫值。
void func(int i);  //由于頂層const被忽略忿危,此處屬于重復(fù)定義。
  • 盡量將函數(shù)不會(huì)改變的形參定義為常量引用没龙。
  1. 數(shù)組形參:為函數(shù)傳遞一個(gè)數(shù)組時(shí)铺厨,實(shí)際上傳遞的是指向數(shù)組首元素的指針缎玫。
  2. 為函數(shù)提供數(shù)組尺寸信息的方法:
    • 使用標(biāo)記指定數(shù)組長度:C風(fēng)格字符串中的結(jié)束符。
    • 使用標(biāo)準(zhǔn)庫規(guī)范:傳遞指向數(shù)組首元素和尾后元素的指針(begin解滓、end函數(shù))赃磨。
    • 顯示傳遞一個(gè)表示數(shù)組大小的形參:size_t類型。
  3. 數(shù)組引用形參:形參可以是數(shù)組的引用洼裤。
  4. 多維數(shù)組:數(shù)組第二維(以及后面所有維度)的大小都是數(shù)組類型的一部分邻辉,不能省略。
  5. 含有可變數(shù)目形參的函數(shù):如果實(shí)參類型相同腮鞍,可傳遞名為initializer_list的標(biāo)準(zhǔn)庫類型值骇;如果實(shí)參類型不同,則使用可變參數(shù)模板(后續(xù)介紹)移国。
  6. initializer_list可提供的操作:
initializer_list<T> lst;  //默認(rèn)初始化吱瘩,T類型元素的空列表。
initializer_list<T> lst{a, b, c...};  //lst元素?cái)?shù)量與初始值一樣多迹缀,lst的元素是對應(yīng)初始值的副本使碾,列表中元素為const。
lst2(lst);
lst2 = lst;  //拷貝或賦值一個(gè)initializer_list對象不會(huì)拷貝列表中的元素祝懂,拷貝后票摇,原始列表和副本共享元素。
lst.size();  //列表中的元素?cái)?shù)量砚蓬。
lst.begin();  //返回指向lst首元素的指針矢门。
lst.end();  //返回指向lst尾后元素的指針。
//Example
void error_msg(initializer_list<string> il);
//調(diào)用形式
if(expected != actual)
  error_msg({"functionX", expected, actual});
else
  error_msg({"functionX", "Okay"});

返回類型和return語句

  1. return語句形式:
    • return ;
    • return expression ;
  2. 無返回值函數(shù):無返回值的return語句只能用在返回類型是void的函數(shù)中怜械。
    • 無返回值的函數(shù)不要求一定return語句颅和,函數(shù)會(huì)隱式執(zhí)行。
    • 使用有返回值的return語句時(shí)缕允,要求expression必須是另一個(gè)返回值為void的函數(shù)峡扩,強(qiáng)行令void函數(shù)返回其他類型的表達(dá)式將引發(fā)編譯錯(cuò)誤。
  3. 有返回值函數(shù):
    • 非void的函數(shù)必須返回一個(gè)值障本。
    • 未返回值便結(jié)束函數(shù)執(zhí)行將引發(fā)未定義行為教届。
  4. 返回的之用于初始化調(diào)用點(diǎn)的一個(gè)臨時(shí)量,該臨時(shí)量即為函數(shù)調(diào)用的結(jié)果驾霜。
    • 不要返回局部對象的引用或指針案训。
    • 返回引用的函數(shù)將返回左值,但只有返回非常量引用時(shí)才可對其賦值粪糙。
  5. 函數(shù)可以返回花括號包圍的值的列表强霎。
  6. 返回值為int的main()函數(shù)可以沒有return語句,編譯器將隱式插入return 0;蓉冈。
    • main()函數(shù)返回0值表示執(zhí)行成功城舞,其他值表示執(zhí)行失敗轩触。
  7. 遞歸:函數(shù)調(diào)用自身。
  8. 返回?cái)?shù)組指針方法:
    • 使用類型別名家夺。
    • Type (*function(parameter_list))[dimension]脱柱。
    • 使用尾置返回類型:auto function(parameter_list) -> Type(*)[dimension]
    • 已知返回的指針將指向哪一個(gè)數(shù)組時(shí),使用decltype拉馋。
int odd[] = {1, 3, 5, 7, 9};
int even[] = {2, 4, 6, 8, 10};
decltype(odd)  *arrPtr(int i)  //decltype并不會(huì)將數(shù)組類型轉(zhuǎn)化為對應(yīng)的指針榨为,所以聲明中需要加*符號。
{
  return (i % 2) ? &odd : &even;
}

函數(shù)重載

  1. 重載函數(shù)的形參數(shù)量煌茴、形參類型應(yīng)有所不同随闺,返回值類型不同不能作為重載函數(shù)。
  2. 函數(shù)重載時(shí)景馁,形參的頂層const屬性會(huì)被忽略板壮,但底層const屬性不會(huì)被忽略。
  3. const_cast在函數(shù)重載中的應(yīng)用:
//比較兩個(gè)string的長度合住,返回較短者的引用
const string &shorterString(const string &s1, const string &s2)
{
  return s1.size() <= s2.size() ? s1 : s2;
}
//要求在實(shí)參不是常量時(shí)绰精,得到普通引用
string &shorterString(string &s1, string &s2)
{
  auto &r = shorterString(const_cast<const string&>(s1), const_cast<string &>(s2));
  return const_cast<string &>(r);
}
  1. 調(diào)用重載函數(shù)時(shí)的可能結(jié)果:最佳匹配,無匹配透葛,二義性調(diào)用笨使。

特殊用途語言特性

  1. 默認(rèn)實(shí)參:
    • 一旦某個(gè)形參被賦予默認(rèn)值,其后出現(xiàn)的所有形參均應(yīng)該有默認(rèn)值(合理設(shè)置形參順序)僚害。
    • 給定作用域內(nèi)硫椰,在函數(shù)的多次聲明中,一個(gè)形參只能被賦予一次默認(rèn)實(shí)參萨蚕。
    • 局部變量不能作為默認(rèn)實(shí)參靶草。
string screen(sz, sz, char = ' ');
string screen(sz, sz, char = '*');  //False
string screen(sz = 24, sz = 80, char);  //True
  1. 內(nèi)聯(lián)函數(shù):返回類型前加上inline關(guān)鍵字,聲明為內(nèi)聯(lián)函數(shù)岳遥,減少調(diào)用開銷奕翔。
    • 適用于規(guī)模較小、流程直接浩蓉、頻繁調(diào)用的函數(shù)派继。
    • 內(nèi)聯(lián)只是向編譯器發(fā)送的一個(gè)請求,編譯器可以忽略此請求捻艳。
  2. constexpr函數(shù):
    • 函數(shù)的返回類型及所有形參的類型均應(yīng)為字面值類型驾窟。
    • 函數(shù)體中有且只有一條return語句。
    • 編譯器將constexpr函數(shù)隱式指定為內(nèi)聯(lián)函數(shù)认轨。
    • 允許constexpr函數(shù)的返回值為非常量绅络。
  3. 內(nèi)聯(lián)函數(shù)和constexpr函數(shù)一般放在頭文件內(nèi)。
  4. 調(diào)試幫助:
    • assert預(yù)處理宏:assert(expr),expr為0時(shí)恩急,assert輸出信息并終止程序執(zhí)行节视,expr非0時(shí),不執(zhí)行操作假栓。
    • NDEBUG預(yù)處理變量:如果定義了NDEBUG,則assert不執(zhí)行任何操作霍掺。
    • _ _func_ _:當(dāng)前調(diào)試的函數(shù)名字匾荆。
    • _ _FILE_ _:存放文件名的字符串字面值。
    • _ _LINE_ _:存放當(dāng)前行號的整型字面值杆烁。
    • _ _TIME_ _:存放文件編譯時(shí)間的字符串字面值牙丽。
    • _ _DATE_ _:存放文件編譯日期的字符串字面值。

函數(shù)匹配

//Example
void f();  //(1)
void f(int);  //(2)
void f(int, int);  //(3)
void f(double, double = 3.14);  //(4)
  1. 確定候選函數(shù)和可行函數(shù):
    • 候選函數(shù):重載函數(shù)集兔魂,需與被調(diào)用函數(shù)同名且其聲明在調(diào)用點(diǎn)可見烤芦。
    • 可行函數(shù):可被調(diào)用這組實(shí)參調(diào)用的函數(shù),要求形參數(shù)量與本次調(diào)用提供的實(shí)參數(shù)量相同析校,且類型相關(guān)构罗。
  2. 尋找最佳匹配:
    • 實(shí)參類型與形參類型越接近,匹配越好智玻。
    • 含有多個(gè)形參的函數(shù)最佳匹配需要滿足該函數(shù)的每個(gè)實(shí)參的匹配都不劣于其它可行函數(shù)需要的匹配遂唧,且至少有一個(gè)實(shí)參的匹配優(yōu)于其它可行函數(shù)提供的匹配。
  3. 調(diào)用錯(cuò)誤:無匹配函數(shù)吊奢、二義性調(diào)用盖彭。
  4. 實(shí)參類型轉(zhuǎn)換等級:
    • 精確匹配,包括:
      • 實(shí)參與形參類型相同页滚。
      • 實(shí)參從數(shù)組召边、函數(shù)類型轉(zhuǎn)化為對應(yīng)的指針類型。
      • 向?qū)崊⒃鰟h頂層const裹驰。
    • 通過const轉(zhuǎn)換實(shí)現(xiàn)的匹配隧熙。
    • 通過類型提升實(shí)現(xiàn)的匹配。
    • 通過算數(shù)類型轉(zhuǎn)換或指針轉(zhuǎn)換實(shí)現(xiàn)的匹配邦马。
    • 通過類類型轉(zhuǎn)換實(shí)現(xiàn)的匹配贱鼻。

函數(shù)指針

  1. 形式:returnType (*function)(parameter_list)
  2. 使用函數(shù)指針:
    • 當(dāng)函數(shù)名作為一個(gè)值使用時(shí),函數(shù)自動(dòng)轉(zhuǎn)化為指針(即取地址符可選)滋将。
    • 可以直接通過指針調(diào)用函數(shù)邻悬,無需解引用指針。
    • 指向不同類型的函數(shù)的指針之間無轉(zhuǎn)換規(guī)則随闽。
    • 函數(shù)指針可賦值0nullptr父丰。
  3. 重載函數(shù)指針:指針類型必須與重載函數(shù)中的某一個(gè)精確匹配。
  4. 函數(shù)指針形參:可以使用類型別名或decltype簡化代碼。
void useBigger(const string &s1, const string &s2, bool pf(const string &, const string &));
//等價(jià)聲明
void useBigger(const string &s1, const string &s2, bool (*pf)(const string &, const string &));  
//Func蛾扇、Func2是函數(shù)類型
typedef bool Func(const string &, const string &);
typedef decltype(lengthCompare) Func2;
//FuncP攘烛、FuncP2是指向函數(shù)的指針
typedef bool (*FuncP)(const string &, const string &);
typedef decltype(lengthCompare) *FuncP2;
//useBigger的等價(jià)聲明
void useBigger(const string &s1, const string &s2, Func);
void useBigger(const string &s1, const string &s2, Func2);
void useBigger(const string &s1, const string &s2, FuncP);
void useBigger(const string &s1, const string &s2, FuncP2);
  1. 返回指向函數(shù)的指針:
    • 直接定義。
    • 使用類型別名镀首。
    • 尾置返回坟漱。
//直接定義
int (*f(int))(int *, int);
//類型別名
using F = int(int *, int);
using PF = int(*)(int *, int);
PF f(int);
F *f(int);
//尾置返回
auto f(int) -> int (*)(int *, int);
  1. 使用auto和decltype可簡化代碼書寫。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末更哄,一起剝皮案震驚了整個(gè)濱河市芋齿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌成翩,老刑警劉巖觅捆,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異麻敌,居然都是意外死亡栅炒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門术羔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赢赊,“玉大人,你說我怎么就攤上這事聂示∮蛐” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵鱼喉,是天一觀的道長秀鞭。 經(jīng)常有香客問我,道長扛禽,這世上最難降的妖魔是什么锋边? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮编曼,結(jié)果婚禮上豆巨,老公的妹妹穿的比我還像新娘。我一直安慰自己掐场,他們只是感情好往扔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著熊户,像睡著了一般萍膛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嚷堡,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天蝗罗,我揣著相機(jī)與錄音,去河邊找鬼。 笑死串塑,一個(gè)胖子當(dāng)著我的面吹牛沼琉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桩匪,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼打瘪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了傻昙?” 一聲冷哼從身側(cè)響起瑟慈,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屋匕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體借杰,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡过吻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔗衡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纤虽。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绞惦,靈堂內(nèi)的尸體忽然破棺而出逼纸,到底是詐尸還是另有隱情,我是刑警寧澤济蝉,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布杰刽,位于F島的核電站,受9級特大地震影響王滤,放射性物質(zhì)發(fā)生泄漏贺嫂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一雁乡、第九天 我趴在偏房一處隱蔽的房頂上張望第喳。 院中可真熱鬧,春花似錦踱稍、人聲如沸曲饱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扩淀。三九已至,卻和暖如春桥温,著一層夾襖步出監(jiān)牢的瞬間引矩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旺韭,地道東北人氛谜。 一個(gè)月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像区端,于是被迫代替她去往敵國和親值漫。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,517評論 1 51
  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型织盼。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一杨何。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,444評論 3 44
  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用沥邻。當(dāng)一個(gè)函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,610評論 1 19
  • 隨著30歲生日的悄悄過去危虱,猛然發(fā)現(xiàn)自己已到而立之年,有些許的迷茫唐全,悲傷埃跷。這個(gè)年紀(jì)正是大家口中所說的事業(yè)成功的時(shí)間,...
    一生最美的美好閱讀 313評論 1 0