函數新特性、內聯函數、const詳解
一、函數回顧與後置返回類型
函數定義中,形參如果在函數體內用不到的話,則可以不給形參變量名字,只給其類型。
函數聲明時,可以只有形參類型,沒有形參名
把函數返回類型放到函數名字之前,這種寫法,叫前置返回類型。
C++11中,後置返回類型,在函數聲明和定義中,把返回值類型放到參數列表之後。
前面放auto,表示函數返回類型放到參數列表之後,而放在參數列表之後的返回類型是通過 -> 開始的。
1 #include <iostream> 2 using namespace std; 3 4 void func123(int , int); // 函數聲明(函數原型); 5void func123(int a,int b)// 函數實現 6 { 7 return; 8 } 9 10 // C++11後置返回類型 11 auto func(int a , int b) -> void; // 函數聲明 12 auto func(int a , int b) -> void 13 { 14 return; 15 } 16 17 inline int myfunc(int testv) // 函數定義前加inline,這個函數為內聯函數 18 { 19 return; 20 } 21 22 23 int main() 24 { 25//函數定義中,形參如果在函數體內用不到的話,則可以不給形參變量名字,只給其類型。 26 func123(12,13); 27 return 0; 28 }
二、內聯函數
在函數定義前加關鍵字inline,導致該函數變成內聯函數。
函數體很小,調用很頻繁,引入inline(內聯函數)
(1)inline影響編譯器,在編譯階段對inline這種函數進行處理,系統嘗試將調用該函數的動作替換為函數本體。通過這種方式來提升性能。
int abc = myfunc(5); //==> int abc = 1;
(2)inline只是我們開發者對編譯器的一個建議,編譯器可以嘗試去做,也可以不做,這取決於編譯器的診斷功能。
(3)內聯函數的定義放到頭文件中。這樣需要用到這個函數的時候能夠通過#include 把這個內聯函數的源代碼#include進來,以便找到這個函數的本體源代碼並嘗試將該函數的調用替換為函數體內的語句。
優缺點:
代碼膨脹的問題;所以內聯函數函數體盡量要小。
註意:各種編譯器對inline的處理各不相同,inline函數盡量簡單,代碼盡量少。循環,分支,遞歸調用盡量不要出現在inline函數中,否則的話編譯器很可能會因為你寫這些代碼的原因拒絕讓這個函數稱為inline函數。
1 constexpr int mf() 2 { 3 // ..寫的特別簡單 4 }
constexpr函數可以看成為更嚴格的內聯函數。
#define 宏展開也類似於inline(內聯函數)。
三、函數雜合用法總結
(1)函數返回類型為void,表示函數不返回任何類型。但是我們可以調用一個返回類型為void的函數,讓它作為另一個返回類型是void的函數的返回值。
1 void funa(){} 2 void funb() 3 { 4 return funa(); 5 //return; 6 }
(2)函數返回指針和返回引用的情況
1 //返回指針 2 int* myfunc() 3 { 4 // 存在隱患 5 int tmpval = 9; 6 return &tmpval; // 這個地址出了這個函數,地址被系統回收。 7 } 8 9 10 int main() 11 { 12 int *p = myfunc(); 13 *p = 6; // 你向一個不存的地址寫了數據 14 } 15 16 //返回引用 17 int& myfunc() 18 { 19 int tmpval = 9; 20 cout << &tmpval << endl; 21 return tmpval; // 也存在隱患 返回已經回收了地址的引用 22 } 23 24 int main() 25 { 26 int& k =myfunc(); 27 cout << &k << endl; 28 k = 10; //你向一個不存的地址寫了數據 29 30 // 返回值 31 int x = myfunc(); // 這種寫法是OK的 32 cout << &x << endl; 33 x = 20; 34 35 return 0; 36 }
(3)不帶形參的函數定義()、(void)
1 int myfunc(void) 2 { 3 return 1; 4 }
(4)如果一個函數如果不調用的話,則該函數只有聲明部分,沒有定義部分。
int a();
int b();
int c();
(5)普通函數定義只能定義(.cpp)一次,聲明可以聲明(.h)多次。
(6)void func(int& a,int& b); 函數可以通過參數引用來實現返回多個值。
(7)C++中,函數允許同名,但是形參列表的參數類型或者數量必須有明顯區別。
void fs(int i);
void fs(float i);
void fs(int i , int b);
四、const char*、char const*、char* const三者的區別
(1)const char* p;
1 int main() 2 { 3 char str[] = “I Love China”; 4 const char* p; // p指向的東西不能通過p來修改(p所指向的目標,目標中的內容不能通過p來改變) 5 p = str; 6 //*p = ‘Y’; // 語法錯誤 7 p++; 8 9 str[0] = ‘Y’; 10 return 0; 11 }
(2)char const* 與 const char*等價
(3)char* const
1 int main() 2 { 3 char str[] = “I Love China”; 4 char* const p = str; // 定義的時候必須初始化 5 // p一旦指向了一個東西之後,就不能再指向其他東西了。 6 *p = ‘Y’; // 但是可以修改p指向的目標中的內容 7 8 //char const* const p = str; 9 const char* const p =str; // p的指向不能變,p指向的內容也不能通過p來改變 10 11 int i = 100; 12 const int& a =i // 代表a的內容不能通過a自己來修改; 13 i=1000; 14 //a = 50; // 不合法 15 16 //int &b = 3; // 錯誤 17 const int &b = 3; // OK 18 //b = 45; // 錯誤 19 cout << b << endl; 20 21 return 0; 22 } 23 24
五、函數形參中帶const
把形參寫成const的好處:
(1)可以防止你無意中修改了形參值導致實參值無意被修改;
(2)實參類型可以更靈活。
1 struct student{int num;}; 2 void fs(const student &stu) 3 { 4 //stu.num = 1010; // 加const stu不可以修改 5 } 6 7 void fs2(const int i) 8 { 9 //i=100; // 不可以修改 10 } 11 12 13 int main() 14 { 15 student student1; 16 student1.num = 100; 17 fs(student1); 18 cout << student1.num << endl; 19 return 0; 20 }
函數新特性、內聯函數、const詳解