C++學習筆記(函數)

函數

函數定義包括:返回類型、函數名字、由0個或多個形參組成的列表以及函數體express

函數調用完成兩項工做:
一、用實參初始化函數對應的形參
二、被控制權轉移給被調用函數數組

函數的返回類型不能是數組類型或函數類型,但可使指向數組或函數的指針函數

形參和函數內部定義的變量統稱爲局部變量,同時還會隱藏在外層做用域中同名的其餘全部聲明優化

局部靜態對象

在程序的執行路徑第一次通過對象定義語句時初始化,而且知道程序終止才被銷燬,在此期間即便對象所在函數結束執行也不會對它有影響命令行

函數聲明(函數原型)

若是一個函數永遠也不會被用到,那麼它能夠只有聲明沒有定義指針

函數聲明與函數定義相似,區別是函數聲明無須函數體,用一個分號代替便可調試

儘可能把聲明放到頭文件中,把定義放到源文件中code

參數傳遞

傳值參數

初始化一個非引用類型的變量,初始值被拷貝給變量。對變量的變更不會影響初始值對象

指針形參

和其餘非引用類型同樣,執行指針拷貝操做時,拷貝的是指針的值,即指針的值不會改變,指針所指對象的值會改變遞歸

傳引用參數

經過使用引用實參,容許函數改變一個或多個實參的值

拷貝大的類類型對象或者容器對象比較低效,甚至有的類類型根本就不支持拷貝操做,當某種類型不支持拷貝操做時,函數只能經過引用型形參訪問該類型的對象

引用類型的形參能夠做爲輸出參數,也可做爲輸入參數,這樣就可實現返回多個值的函數

const 形參和實參

當用實參初始化形參時會忽略掉頂層const,因此在函數重載時,const int i = int i

指針或引用形參與 const

可使用很是量初始化一個底層 const 對象,反過來不行,一個普通的引用必須用同類型對象初始化

儘可能使用常量引用

數組形參

不容許拷貝數組、使用數組時一般會將其轉換成指針

使用標記指定數組長度

相似字符串以'0'結束

使用標準庫規範

傳遞指向數組首元素和尾後元素的指針

顯式傳遞一個表示數組大小的形參

專門定義一個表示數組大小的形參

main:處理命令行選項

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

第二個形參argv是一個數組,它的元素是指向C風格字符串的指針,第一個形參argc表示數組中字符串的數量
容許main函數沒有return語句直接結束,編譯器會隱式插入一條返回0的return語句,返回0表示成功,返回其餘值表示失敗,非0值的具體含義依機器而定

含有可變形參的函數

若是全部的實參類型相同,能夠傳遞一個名爲initializer_list 的標準庫類型;
若是實參的類型不一樣,能夠編寫一種特殊的函數,也就是所謂的可變參數模板
C++還提供了一種特殊的形參類型(即省略符),能夠用它傳遞可變數量的實參,這種功能通常只用於與C函數交互的接口程序

initializer_list 形參

提供的操做爲:
initializer_list<T> lst; 默認初始化;T類型元素的空列表
initializer_list<T> lst{a, b, c} lst的元素數量和初始值同樣多;lst的元素是對應初試值的副本,列表中的元素是const
lst2(lst) 拷貝或複製一個initializer_list對象不會拷貝列表中的元素,拷貝後,原始列表和副本共享元素
lst2 = lst
lst.size() 列表中的元素數量
lst.begin() 返回指向lst中首元素的指針
lst.end() 返回指向lst中尾元素下一個位置的指針
initializer_list 對象中的元素永遠是常量值,沒法改變元素的值
若是想向initializer_list形參中傳遞一個值的序列,必須把序列放在一對花括號內

省略符形參

只能出如今形參列表的最後一個位置,形式有如下兩種:

void foo(parm_list, ...);
void foo(...);

返回類型和return語句

return語句終止當前正在執行的函數並將控制權返回到調用該函數的地方
return有兩種形式:

return;
return expression;

不要返回局部對象的引用或指針
調用運算符的優先級與點運算符和箭頭運算符相同,符合左結合律

列表初始化返回值

C++11容許函數返回花括號包圍的值的列表
若是函數返回的是內置類型,則花括號包圍的列表最多包含一個值,並且該值所佔空間不該該大於目標類型的空間,若是函數返回的是類類型,由類自己定義初始值如何使用

遞歸

一個函數直接或間接調用自身,就稱該函數爲遞歸函數

返回數組指針

方法一:使用類型別名

typedef int arrT[10];
using arrT = int[10];
arrT *func(int i);

方法二:聲明一個返回數組指針的函數
形式爲:

Type(*function(parameter_list))[dimension]

Type 表示元素的類型,dimension表示數組的大小
例如:int (*fun(int i))[10];
方法三:使用尾置返回類型
例如:auto func(int i) -> int(*)[10];
方法四:使用decltype
例如:

int odd[] = {1, 3, 5, 7, 9};
int even[] = {0, 2, 4, 6, 8};
decltype(odd) *arrPtr(int i)
{}

函數重載

函數名字相同,形參數量或者形參類型不一樣,不容許兩個函數除了返回類型外其餘全部要素相同

重載和const形參

一個擁有頂層const的形參沒法和另外一個沒有頂層const的形參區分開來
若是形參是某種類型的指針或引用,則經過區分其指向的是常量對象仍是很是量對象能夠實現函數重載,此時const是底層的

調用重載的函數

當調用重載函數的時候有三種可能結果:
編譯器找到一個實參最佳匹配的函數,並生成調用該函數的代碼
找不到任何一個函數與調用的實參匹配,此時編譯器發出無匹配的錯誤信息
有多於一個函數能夠匹配,可是每個都不是明顯的最佳選擇,此時發生二義性調用的錯誤

默認實參

一旦某個形參被賦予了默認值,其後全部形參都必須有默認值,若是調用時想用默認實參,只要在調用時省略該實參
在給定的做用域中一個形參只能被賦予一次默認形參
局部變量不能做爲默認實參

內聯函數和constexpr函數

內聯函數

將函數指定爲內聯函數,就是將它在每一個調用點上內聯地展開,消除運行時開銷
內聯機制用於優化規模較小,流程直接,頻繁調用的函數

constexpr函數

constexpr函數指能用於常量表達式的函數
函數的返回類型及全部形參的類型都得是字面值類型,並且函數體重必須有且僅有一條return語句
constexpr函數被隱式指定爲內聯函數
容許constexpr函數返回值並不是一個常量

內聯函數和constexpr函數能夠在程序中屢次定義,一般定義在頭文件中

調試幫助

assert預處理宏

是一個預處理變量,相似內聯函數,使用一個表達式做爲它的條件:

assert(expr);

對expr求值,表達式爲假,輸出信息並終止程序執行,表達式爲真,什麼也不作,定義在cassert頭文件中,assert宏用於檢查「不能發生」的條件

NOEBUG預處理變量

assert行爲依賴於一個名爲NOEBUG的預處理變量的狀態,若是定義了NOEBUG,則assert什麼也不作,默認狀態下沒有定義NOEBUG,此時assert將執行運行時檢查
可使用#define語句定義NOEBUG,關閉調試狀態
定義NOEBUG避免檢查各類條件所需的運行時開銷,assert應僅用於驗證那些不可能發生的事情
可用NOEBUG編寫本身的條件調試代碼,若是NOEBUG未定義,將執行#ifndef和#endif之間的代碼,若是定義了NOEBUG,這些代碼將被忽略

void print(const int ia[], size_t size)
{
#ifndef NDEBUG
        //__func__是編譯器定義的一個局部靜態變量,用於存放函數的名字,以一個const char靜態數組
    cerr << __func__ << ": array size is" << size << endl;
#endif
//...

FILE 存放文件名的字符串字面值
LINE 存放當前行號的整型字面值
TIME 存放文件編譯時間的字符串字面值
DATE 存放文件編譯日期的字符串字面值

函數匹配

一、選定本次調用對應的重載函數集,集合中的函數稱爲候選函數集,集合中的函數稱爲候選函數
候選函數有兩個特徵:與被調用函數同名,聲明在調用點可見
二、考察本次調用可提供的實參,而後從候選函數中選出能被這組實參調用的函數,這些新選出的函數稱爲可行函數
可行函數有兩個特徵:形參數量與本次調用提供的實參數量相等,每一個實參的類型與對應的形參類型相同
若是函數含有默認實參,則咱們調用該函數時傳入的實參數量可能少於它實際使用的實參數量
三、從可行函數中選擇與本次調用最匹配的函數
若是有且僅有一個函數知足下列條件,則匹配成功:
· 該函數每一個實參的匹配都不劣於其餘可行函數須要的匹配
· 至少有一個實參的匹配優於其餘可行函數提供的匹配

實參類型轉換

一、精準匹配
· 實參類型和形參類型相同
· 實參從數組類型或函數類型轉換成對應的指針類型
· 向實參添加頂層const或者從實參中刪除頂層const
二、經過const轉換實現的匹配
三、經過類型提高實現的匹配
四、經過算術類型轉換或指針轉換實現的匹配
五、經過類類型轉換實現的匹配

函數匹配和const實參

若是重載函數的區別在於它們的引用類型的形參是否引用了const,或者指針類型的形參是否指向const,則當調用發生時編譯器經過實參是不是常量來決定選擇哪一個函數

函數指針

指向函數,類型由它的返回類型和形參類型共同決定,與函數名無關函數名做爲一個值使用時,函數自動轉換成指針可直接用指向函數的指針調用函數,無需提早解引用指針函數指針可做爲形參和實參decltype返回函數類型,不會將函數類型自動轉換成指針類型返回類型不會自動轉換成指針,必須顯式將返回類型指定爲指針

相關文章
相關標籤/搜索