目錄結構:
1.簡介
通常函數包括形參,函數名,函數主體,函數返回值。下面的案例展示了c++函數使用的基本語法規則:
int add(int,int);//add函數的聲明 int main(int argc,char *argv[]){ int res = add(1,1); return 0; } //add函數的定義 int add(int a,int b){ return a+b; }
也可以不用寫add函數的聲明,直接把的add函數的定義寫在main函數的上面:
int add(int a,int b){//add函數的定義 return a+b; } int main(int argc,char *argv[]){ int res = add(1,1); return 0; }
2.可變形參的函數
c++支持可變形參的函數,可以使用initializer_list來實現或是省略符來實現。
2.1 initializer_list形參
如果函數的實參數量未知,但是全部的實參類型都相同,那么就可以使用initializer_list類型的形參。在使用initilizer_list類型之前,必需先引用<initilizer_list>頭文件。
initializer_list是一種模板類型,應此在使用時必需說明所含元素的類型,例如:
initializer_list<string> ls; //initializer_list元素中的類型是string initializer_list<int> li; //initializer_list元素中的類型是int
注意:initializer_list對象中的元素值永遠是常量,我們無法改變initializer_list對象中元素的值。
#include <iostream> #include <initializer_list> using namespace std; void error_msg(initializer_list il){ for(auto beg=il.begin(); beg != il.end(); beg++) cout << *beg << " "; cout << endl; } int main(int argc,char *argv[]){ error_msg({"error message 1","error message 2"});//調用error_msg函數 return 0; }
2.2 省略符形參
省略符形參只能用在形參列表的最后一個位置
例如:
#include <iostream> /*cout,endl*/ #include <cstdarg> /*va_list,va_start,va_end*/ int sum(int count, ...) { //格式:count代表參數個數, ...代表n個參數 va_list ap; //聲明一個va_list變量 va_start(ap, count); //第二個參數表示形參的個數並且只能是參數列表中最后一個被命名了的參數。 int sum = 0; for (int i = 0; i < count; i++) { sum += va_arg(ap, int); //第二個參數表示形參類型 } va_end(ap); //用於清理 return sum; } int main(int argc,char **argv){ cout << sum(5,1.1,2.2,3.3,4.4,5.5) << endl; return 0; }
3.main函數處理命令行選項
main函數是應用程序的入口函數,它有如下幾種形式:
int main(){} int main(int argv,char *argv[]){} int main(int argv,char **argv){}
第一種形式main函數不接收任何參數。
第二種形式main函數,其中第一個形參argc表示數組的大小;第二個形參argv表示一個數組,它的元素是指向C風格字符串的指針。
int main(int argc,char *argv[]){ for(decltype(argc) index=0; index<argc; index++) cout << argv[index] << " "; cout << endl; return 0; }
第三種形式main函數,argv是一個指針,指向一個char*類型。
int main(int argc,char **argv){ for(decltype(argc) index=0; index<argc; index++) cout << (*argv++) << " "; cout << endl; return 0; }
若將上面的程序命名為test.cpp,在編譯成功后,使用如下命令運行:./test how are you
輸出結果為:
./test how are you
從結果中可以看出,"./test"並不是我們想輸出的(我們本意是想輸出"how are you")。應此需要注意,main函數中,實際的參數應該從下標1開始。
4.函數指針與函數引用
函數指針,顧名思義就是指向函數的指針。同理,函數引用就是引用函數的引用。
例如:
bool (*pf)(const string&,const string&);
pf前面有一個*,因此pf是指針;右側是形參列表,表明pf指向函數;再觀察左側,發現函數的返回值類型是布爾值。因此pf就是一個指向函數的指針,其中函數具有兩個const string&形參,返回值是bool類型。
注意:
如果pf是這樣的話
bool *pf(const string&,const string&)
那么pf就不是函數指針了,這種情況下pf表示為一個函數,函數具有兩個const string&類型的形參,和一個bool指針類型的返回值。
當把函數名作為一個值使用時,該函數自動地轉化為指針。同時還能直接使用指向函數的指針調用該函數,無須提前解引用。
#include <iostream> /*cout,endl*/ using namespace std; int compare(const string& a,const string& b){ return a.compare(b); } int compare(const int& a,const int& b){ return a - b; } //定義一個函數,其形參為另一個函數 void test1(int (*p)(const string&,const string&)){ p("hello","world"); }; //test2和test1是等價聲明,函數類型會自動轉化為指向函數的指針 void test2(int p(const string&,const string&)){ p("hello","world"); }; //test3返回一個函數指針,該指針具有兩個int類型的形參,返回值類型為void void (*test3())(int,int){ } //test4和test3是等價聲明 auto test4()-> void (*)(int,int){ } void (*test5( int (*p)(const int&,const int&) ))(int,int){ p(1,2); return 0; } int main(int argc,char **argv){ int (*pf)(const string&,const string&);//聲明一個函數指針 pf=0;//pf不指向任何函數 pf = compare;//pf指向 int compare(const string&,const string&) int res = pf("hello","world");//調用pf所知指函數,無需提前解引用 int (&rpf)(const int&,const int&) = compare;//聲明一個引用,初始化為compare(compare有兩個重載函數,這里引用形參為兩個的const int&的函數) int res = rpf(1,2);//調用rpf所引用的函數 test1(compare);//傳遞方法作為實參,也可以參數函數指針作為實參。 void (*p)(int,int) = test3();//返回一個函數指針 p = test5(rpf);//接受一個函數指針,返回一個函數指針。rpf會自動轉化為函數指針 return 0; }
5.inline內聯函數
inline函數被稱為內聯函數,就是將它在每個調用的節點上“內聯地”展開。
在函數定義的時候加上inline關鍵字,這樣就成為內聯函數了。
#include <iostream> #include <string> using namespace std; //shoterString函數接受兩個const string類型參數,返回一個const string&類型的數據,同時該函數是內聯函數。 inline const string & shoterString(const String s1,const String s2){ return (s1.size() < s2.size() ? s1 : s2); } int main(int argc,char *argv[]){ string s1 = "hello"; string s2 = "world"; //編譯時轉化為cout << (s1.size() < s2.size() ? s1 : s2) << endl; cout << shoterString(s1,s2) << endl; }
一般來說,內聯機制用於規模較小,流程直接,頻繁調用的函數。很多編譯器都不支持內聯遞歸函數。
6.Constexpr函數
constexpr是c++11新標准添加的關鍵字,該關鍵字主要用於提供程序的運行效率,使用constexpr指定的值和函數能夠在編譯時進行計算,比如下面的product()將會在編譯時被計算:
constexpr int product(int x, int y) { return (x * y); } int main() { //在編譯后,會直接轉化為 const int x = 200; const int x = product(10, 20); cout << x; return 0; }
輸出結果為:
200
使用constexpr函數有以下幾點約束:
1.在c++11中,一個constexpr函數只能有一個return語句。c++14標准中,允許超過一個return語句。
2.constexpr函數應該只引用常量全局變量
3.constexpr函數能夠調用其他constexpr函數,不能調用非constexpr函數。
4.constexpr函數不能返回void類型,還有一些操作符比如(++v,--v)都不允許出現在constexpr函數。