c過渡c++應知應會(2)
- 1.缺省參數
- 2.函數重載
- 3.引用
- 4.inline
1.缺省參數
缺省參數是聲明或定義函數時為函數的參數指定一個缺省值。在調用該函數時,如果沒有指定實參,則采用該形參的缺省值,否則使用指定的實參,缺省參數分為全缺省和半缺省參數。
全缺省:
全部形參給缺省值。
半缺省:
部分形參給缺省值。
注意:c++規定半缺省參數必須從右往左依次連續缺省,不能跳躍的給。
調用帶缺省參數的函數時,必須從右往左依次給實參,不能跳躍的給。
關鍵:
函數聲明和定義分離時,缺省參數不能在函數聲明和定義中同時出現,規定必須在聲明中給缺省值
int add(int a, int b=1)//半缺省
{return a + b;
}
int main()
{add(1);//b使用缺省值return 0;
}
int add(int a=1, int b=1)//全缺省
{return a + b;
}
int main()
{add();//沒有傳參的話,使用缺省值return 0;
}
2.函數重載
在上一次學習中我們知道c++支持在不同域使用同名變量,函數等。
除此之外,c++還可以在同一作用域出現同名函數。
但是有些人就要問了,為什么非得創建同名函數呢?名字不一樣不照樣可以使用嗎?
讓我們看這個例子:
int Add1(int l,int r)
{return l+r;
}
double Add1(double l,double r)
{return l+r;
}
我們想實現兩個數相加函數,但針對不同類型時卻可能要將函數名變成Add1,Add2…
這無疑會在將來調用時產生隱患。所以c++支持出現同名函數,要求同名函數的形參不同,可以參數個數不同或者類型不同。
int Add(int l,int r)
{return l+r;
}
double Add(double l,double r)
{return l+r;
}
這樣在將來調用相加函數時,一律寫成Add即可。
這段代碼有問題嗎?
void func()
{std::cout << "fun()" << std::endl;
}
void func(int a = 10)
{std::cout << "func(int a)" << std::endl;
}
毋庸置疑,兩個函數構成重載。如果程序中沒有func();就不會報錯,但是如果有這一條語句,編譯器就不認得到底要調用哪一個函數。
3.引用
概念:引用就是給已存在變量取了一個別名。
編譯器不會為引用變量開辟內存空間。它和它引用的變量共用同一塊內存空間。
例如:這里有一只貓,你可以叫它貓,也可以叫它哈基米,也可以叫它專屬的名字。
定義方式:
類型& 引用別名 = 引用對象
int main()
{int a = 0;int& b = a;a++;std::cout << b << std::endl;//輸出結果為1return 0;
}
關于引用需要注意的點:
1.引用在定義時必須初始化,例如int a = 0; int& b = a;不允許等號右邊沒有變量。
**2.**一個變量可以有多個引用。
**3.**引用只能引用一個實體,不能改變
引用的用處:
在c語言階段,我們經常使用指針來操作并解決問題。有了引用后,指針涉及到的一些場景就可以被替代了。而且引用理解起來要比指針容易,能減輕代碼錯誤。
例如,在交換兩個變量的值時:
void Swap(int& a,int& b)
{int tmp=a;a=b;b=tmp;
}
這樣寫非常容易理解。
再比如,在學習數據結構棧時,我們在操作改動棧時,必須要用一級指針來傳參。但有了引用以后,我們可以直接傳引用。比方說在入棧時:我們直接進行操作即可,不用使用->操作符了
void STPush(ST& rs, STDataType x)
{assert(ps);// 滿了, 擴容 if (rs.top == rs.capacity){printf("擴容\n");int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}rs.a = tmp;rs.capacity = newcapacity;}rs.a[rs.top] = x;rs.top++;
}
4.inline
用inline修飾的函數叫做內聯函數,編譯時編譯器會再調用的地方展開內聯函數,這樣就不需要建立棧幀,提高效率了。
inline int add(int a, int b)
{return a + b;
}
int main()
{//如果匯編中有call add語句就是沒有展開,否則就是展開了add(1, 2);return 0;
}
注意:
-
在vs編譯器debug版本下默認是不展開inline,這樣方便調試。
(出現了call add說明沒有展開) -
inline不建議聲明和定義分離到兩個文件。因為如果inline被展開,就沒有函數地址。在鏈接階段,鏈接器需要根據函數調用找到對應的函數定義,但此時可能找不到該函數的地址,從而導致鏈接錯誤。
完
如果發現錯誤,歡迎打在評論區。
主頁還有更多優質內容OvO