目錄
1.缺省(sheng)參數
2.函數重載
3.引用
3.1引用的概念和定義
3.2引用的特性
3.3引用的使用
3.4const引用
3.5.指針和引用的關系
4.nullptr
5.總結
1.缺省(sheng)參數
(1)缺省參數是聲明或定義是為函數的參數指定一個缺省值。在調用該函數是,如果沒有指定實參則采用該形參的缺省值,否則使用指定的實參,缺省參數分為全缺省和半缺省參數。
如:
#include<iostream>
using namespace std;
void Func(int n)
{cout << n << endl;
}
void Func1(double n = 4.1)
{cout << n << endl;
}
int main()
{Func(2);Func();Func1(2);Func1();return 0;
}
我們在C語言中如果在有參數的時候不傳參就會報錯,而在C++中如果我們不在聲明或定義中設置缺省值都會導致運行出錯,但是如果我們在定義時加個缺省值也不會使Func()報錯,如:
#include<iostream>
void Func(int n = 4);
using namespace std;
void Func(int n)
{cout << n << endl;
}
void Func1(double n = 4.1)
{cout << n << endl;
}
int main()
{Func(2);Func();Func1(2);Func1();return 0;
}
這樣就不會有問題,但是最終結果為什么呢?
我們發現我們不傳參也會讓函數執行該語句,如果我們在定義時設置缺省值而在聲明中不設置缺省值結果會怎么樣呢?
但是如果我們把聲明和定義放在不同文件中呢?
最終都還是能正常打印結果的,所以我們設置缺省值的時候放在哪里都可以。
(2)全缺省:全部參數都給缺省值,半缺省:部分形參給缺省值。
(3)帶缺省參數的函數調用,C++規定必須從左到右依次給實參,不能跳躍給實參。
void Func(int a = 10, int b = 20, int c = 30)
{cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{Func(1, 2, 3);Func(1, 2);Func(1);Func();Func(, 2, 3);Func(, , 3);return 0;
}
我們發現如果順序給實參就不會報錯,不給實參也不會報錯,但是跳躍給實參就會報錯,這是規定的,我們不能改變,所以以后使用時要注意了哦!
(4)缺省參數在函數聲明和定義中同時出現,規定必須在函數聲明給缺省值。
void Func(int n = 0 );
void Func(int n = 1)
{cout << n << endl;
}
int main()
{Func();return 0;
}
運行結果為:
我們如果在給聲明和定義的缺省值不同的時候就會報錯,這個時候我們要及時調整定義的缺省值了,可以不給,但是必須要在聲明中給,因為我們之后要改的時候就好改一些,只是現在我們的代碼量不多,之后代碼量多了就會知道為啥了,我們都把聲明放在頭文件中,之后修改直接在里面修改就可以了!(4)中的知識我們可以不遵循,但是建議要遵循!
2.函數重載
C++支持在同一個作用域中出現同名函數,但是要求這些同名函數的形參不同,可以是形參類型不同,也可以是形參個數不同,如:
void Func(int a, int b ,int c)
{cout << a << ' ' << b << c << endl;
}
void Func(double a, int b)
{cout << a << ' ' << b << endl;
}
void Func()
{cout << endl;
}
void Func(int a, int b)
{cout << a << ' ' << b << endl;
}
int main()
{Func(1, 2, 3);Func(1.1, 2);Func();Func(1, 2);return 0;
}
由于我們沒有給' '所以第一行結果我們就沒有出現1 2 3
但是如果我們給缺省值呢?
我們的Func()不知道到底是調用哪一個函數,所以會造成報錯的問題,所以我們的重名函數建議不要給缺省值,否則很容易造成報錯的!至于給缺省值的好處,之后就會知道,現在我們是先簡單了解一下。
3.引用
3.1引用的概念和定義
引用是給一個變量取別名,而不是新定義一個變量,也不需要新開辟一塊空間,引用的變量和被引用的變量共用同一塊空間,如:林沖的別名是豹子頭,我們可以叫林沖為豹子頭,也可以叫他林沖。引用的寫法:int a=0;int& b=a;這個b就是a的別名。其中b的類型還是為int相當于&的前面的變量類型就是引用變量的類型。
3.2引用的特性
(1)引用在定義時必須初始化。我們不能直接int& b;
(2)一個變量可以有多個引用。如:int a=0;int& b=a;int& c=a;
(3)引用一旦引用一個實體就再不能引用其他實體,也就是說引用只能引用一次,比如:
int x=10;int y=0;int& d=y;d=x;
d=x的意思到底是把x的值賦值給d(y)還是給x取別名為d呢?
3.3引用的使用
(1)引用在實踐中主要是引用傳參和引用做返回值中減少拷貝提高效率和改變引用對象時同事改變被引用對象。
這句話很難理解,我一句一句來講,比如我們常用的交換函數就可以來用引用:
void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
這樣我們就不需要進行指針的調用了,因為都是一個地址的數據改變。為什么會有“和”后面的內容呢?因為我們的意思就是如果傳的參數分別為x,y那么如果a,b改變,那么x,y的值也改變。而這樣也不用進行值的拷貝,相對于之前的指針簡單多了!
此外,引用也可以給指針變量取別名,可以給結構體取別名,相當于typedef a b;但是我們的a,b只能為變量類型而不能為變量!
如果我們換一個思路來思考:如果我們要增加或減少棧頂所存的數據,那么我們該如何做?
按照之前的思路,我們先取棧頂元素,比如我們要加10,那么我們就讓這個棧頂元素加等10,然后把出棧,然后再把結果入棧。但是這樣非常麻煩!我們可以直接STTop(s)+=10;在之前看來是不行的,但是這是C++啊,C++規定:返回值具有常性,就相當于被const修飾了。而返回值是臨時對象(之后再講),就相當于臨時對象具有常性。所以我們不能通過返回值來修改,而且我們僅僅是改變的只是返回值的結果卻不能真正改變棧頂數據,所以我們需要用引用來了。我們之前在定義這個函數時是用的指針吧,現在我們把這個*改為&不也是一樣嗎,我們這樣改了就可以STTop+=10了,因為就是相當于地址所存儲的值發生改變了!
需要注意我們不能在函數除了形參外取別名的,因為這樣后面空間回收了,而這個地址已經不存儲任何數據了就沒有任何作用了,所以我們不能進行取別名的操作。
(2)使用引用代替指針傳參可以簡化程序,避免復雜的指針,其中,結點的結構只能用指針來寫,因為需要指針來進行指針指向的改變,而引用卻不能改變!
3.4const引用
(1)可以引用一個const對象,但是必須用const引用。const引用也可以引用普通對象,因為對象的訪問的權限在引用過程中可以縮小,但是不能放大。
第一句話我們需要用第二句話來理解,我們知道const意味著不可修改,如果我們取了一個別名就變成可修改了,這樣是很危險的!因為二者都是一個東西,權限不能擴大。所謂權限就是說變量能修改就是權限大了,不能修改就是權限小了。所以引出第一句話。
const引用也可以引用普通對象,比如:我今天本來準備吃飯,但是人太多了或者有意外的情況下我不準備吃了。這意味著我今天不吃飯,但是后面還是要吃飯的,這是權限縮小,比如:int?a=10; const int& c=a;這樣的形式是可以的。但是如果const int a=10; int& b=a;這就涉及到權限擴大,是不可以的。
(2)如果我們傳參是用另外一個變量類型來傳參或者用表達式來傳參的情況下,這會生成一個臨時對象,這個臨時對象具有常性,不可修改。
所以我們可以:const int& b=a*3;但是不可以int& b=a*3因為這個a*3轉化為b會涉及到產生臨時對象,而這個臨時對象在生成的過程中會產生一個別名來存儲這個值,而這個別名也是不可修改的,所以我們在進行運算賦值給一個普通引用時就不可以,要用const引用(常引用)。還有一種情況:double d=10.1;int& b=d;會報錯,不是d轉化為b報錯,是因為類型轉換時會產生一個臨時對象來存儲d的小數點前面部分,而這個值也不可修改,所以我們需要const int& b=d
為什么要進行這樣?
void func(int& a)
{cout << a << endl;
}
int main()
{int a = 10;func(a);func(10);func(3.14);func(a * 3);return 0;
}
我們不能傳參以除變量的任何形式,至于原因之前都解釋了,但是如果我們加const引用就可以了:
void func(const int& a)
{cout << a << endl;
}
int main()
{int a = 10;func(a);func(10);func(3.14);func(a * 3);return 0;
}
這樣會使傳參的時候類型更豐富。
3.5.指針和引用的關系
二者都有各自的特點,互相不可替代,功能有重疊性。
(1)語法上引用為一個變量取別名,不開辟新空間,指針是存儲一個變量地址,要開辟新空間;
(2)引用在定義時,必須初始化,指針建議初始化,但是語法上不是必須的;
(3)引用在初始化引用一個對象后,就不能再引用其他對象,而指針可以不斷地改變指向對象;
(4)引用可以直接訪問指向對象,而指針需要結引用才能訪問指向對象;
(5)sizeof兩個東西的含義不同,引用結果為引用類型大學,但指針始終是地址空間鎖占字節數;
(6)指針很容易出現空指針和野指針的問題,引用很少出現問題,引用使用起來相對更安全一些(除非引用對象被銷毀)。
建議使用引用,指針也可以用,看情況。
4.nullptr
NULL實際是一個宏,在傳統C中包含于stddef.h中,在C++中我們如果用NULL,則會打印出0,因為在C++會轉換為0,所以相當于直接打印0了,而在C語言中NULL定義為((void*)0),如果打印的話就會報錯,因為無法識別。所以我們用nullptr來代替NULL,以防這兩個問題。所以我們之后在使用NULL時把NULL改為nullptr即可。
5.總結
這章內容有點上難度了,但是總體來說理解不是很難,主要掌握引用的用法就可以了,其他的不是太大的問題。喜歡的可以一鍵三連哦,下次再見!