C++入門教程之引用與指針
前言
之前的文章我們已經(jīng)介紹了C++中的基本類型如int,bool和double等,除了基本類型C++還有一些更復(fù)雜的數(shù)據(jù)類型復(fù)合類型,所謂的復(fù)合類型就是通過其他類型定義的類型,本篇文章我們將會著重介紹C++的復(fù)合類型引用和指針。
引用
一個引用是定義一個對象的別稱,一個引用類型是指向其他類型的,下面就是引用聲明的例子。
int val = 1024; int &refVal = val; //refVal指向val int &refVal2; //錯誤,引用必須初始化
通常來說,當(dāng)我們初始化一個變量,初始化的值就會拷貝進(jìn)我們創(chuàng)建的對象,當(dāng)創(chuàng)建一個引用時,不是拷貝初始化的值,而是將引用與初始化的對象綁定,一旦初始化,一個引用就是保持與初始化對象的綁定,且無法重新綁定,所以引用必須要初始化。
指針
指針是一個復(fù)合類型指向其他的類型,就像引用,指針也是用于間接獲取對象,但是與引用不同,指針是一個對象,它擁有對象有的能力,一個指針可以賦值和拷貝,在它的生命周期內(nèi),一個指針可以指向多個對象,且指針無需在定義時就初始化,就像其他的基本類型,如果其范圍內(nèi)沒有初始化會有一個默認(rèn)值,以下就是指針的聲明,*是指針操作符。
int *p1, *p2; double dp, *dp2;
指針與地址
一個指針持有一個對象的地址,可以同地址操作符(&)獲取地址。
int val = 42; int *p = &val;
上面的例子中,第二個表達(dá)式定義了一個int指針p,且初始化p指向一個叫做val的int對象,因?yàn)橐貌皇菍ο鬀]有地址,所以我嘛不會定義一個指針指向一個引用。
需要注意的是指針的類型要與指向?qū)ο蟮念愋拖嗤?,否則就會發(fā)生錯誤
double dval; double *pd = &dval; //沒問題 double *pd2 = pd; //沒問題 int *pi = pd; //報(bào)錯, pi與pd類型不一致
以上例子就睡報(bào)錯不能用int *類型初始化double , 可以將與基本類型的組合理解為一個新的類型。類型必須匹配,因?yàn)樾枰ㄟ^指針的類型來推斷指針指向?qū)ο蟮念愋停缰八岬降?,一個對象的類型決定了其所支持的操作,如果類型不一致會導(dǎo)致操作失敗。
指針的值
指針的值(地址)有以下四種情況
- 指向一個對象
- 指向緊鄰對象所占空間的下一個位置
- 空指針,意味著未指向任何對象
- 無效指針,也就是上述情況之外的值
拷貝和獲取一個無效指針會引發(fā)錯誤,編譯器并不負(fù)責(zé)檢查此類錯誤,訪問無效執(zhí)政的后果是無法預(yù)計(jì)的,所以程序員必須要清楚的知道所給指針是否有效。雖然第2和第三種情況指針是有效的,但是使用上還是有很多限制,因?yàn)樗鼈儾]有指向一個對象,如果我們通過它們獲取對象,其結(jié)果也是未知的。
指針獲取對象
當(dāng)一個指針指向一個對象時,我們可以通過解引用操作符*來獲取對象
int val = 42; int* p = &val; //p持有val的地址,p是指向val的指針 std::cout<<*p; //*p獲取p指向的對象
一些符號如和&在表達(dá)式和聲明中都會使用到,其中符號所處的上下文決定其含義,在聲明中,&和是用于形成復(fù)合類型,在表達(dá)式中這些符號代表一種操作,雖然是相同的符號但是含義完全不同,最好好的方法就是忽略它們的表象,將其視為不同的符號,以下例子中就詳細(xì)說明了兩種符號不同場景下的不同含義。
int val = 42; int &r = val; //&在類型的后面是聲明的一部分,r是一個引用 int *p; //*在類型的后面是聲明的一部分,p是一個指針 p = &val; //&在表達(dá)式中,所以是取地址操作符 *p = val; // *在表達(dá)式中,是解引用操作符 int &r2 = *p; //&是聲明的一部分,*是解引用操作符
空指針
空指針沒有指向任何對象,在使用一個指針前可以先檢查其是否為空,獲得空指針的方式有以下幾種:
int *p1 = nullptr; //等價于int *p1 = 0 int *p2 = 0; //直接通過字面量0來初始化 int *p3 = NULL; //等價于int *p3 = 0
最直接的方法獲取空指針就是nullptr,這也是新標(biāo)準(zhǔn)引進(jìn)的方法,也可以通過字面量0來初始化指針,在一些老的程序中會使用預(yù)處理變量NULL,在cstlib頭文件中將其定義為0,至于預(yù)處理器的內(nèi)容之后會詳細(xì)介紹。
需要注意將一個int值賦予一個指針是不合法的,即使是0也不行
int zero = 0; pi = 0 //錯誤
未初始化的指針是一個很常見的運(yùn)行時錯誤,正如使用其他未初始化的變量一樣,使用一個未初始化的指針結(jié)果也是未知的,絕大多數(shù)情況使用未初始化的指針會導(dǎo)致運(yùn)crash,而且在debug時很困難。 在大多數(shù)的編譯器中,如果使用一個未初始化的指針,內(nèi)存中該指針存儲的內(nèi)容會被當(dāng)作一個地址,而且無法分辨該地址是否有效,如果是無效地址則會crash,如果是有效地址則可能會發(fā)生未知錯誤。 所以建議初始化所有的變量,尤其是指針,如果可能的話,只在指針需要指向的對象定義后定義指針,如果實(shí)在沒有指向的對象,初始化為nullptr或0,這樣程序可以檢測到指針沒有指向一個對象。
指針與賦值
指針和引用都是提供間接訪問對象的方法,但是二者還是有很大的差別,其中最大的差別就是引用不是一個對象,一旦我們定義了一個應(yīng)用就沒有辦法讓它指向另一個對象,當(dāng)我們使用引用的時候我們只會獲得其最初綁定的對象。指針和其持有的地址之間的關(guān)系并不保證,當(dāng)我們給一個指針賦值一個非引用對象時,將會給指針自身一個新的值。賦值讓指針指向一個不同的對象。
int i = 0; int *pi = 0; //pi被初始化但是沒有指向?qū)ο? int *pi2 = &i //pi2被初始化且地址指向i int *pi3; //pi3定義了但是沒有初始化 pi3 = pi2; //pi2和pi3指向同一個對象 pi2 = 0; //pi2不指向任何對象
有時候很難直接看出來賦值是改變了指針還是改變了指針指向的對象,最重要就是記住賦值改變左邊的操作數(shù),例子如下,我們給pi賦值改變的是pi持有的地址。
pi = &ival; //pi的值改變,現(xiàn)在pi指向ival
與此同時,以下例子是*pi(pi指向的值)改變了
*pi = 0;
void*是一個特殊的指針類型,其可以持有任何類型的對象的地址,
理解復(fù)合類型
正如我們所看到的,一個變量定義包含了一個基本類型和一系列的聲明符,每一個聲明符與其相關(guān)的基本類型變量關(guān)聯(lián),且與其他在同一個定義里的聲明符無關(guān),所以一個定義可以定義多個不用類型的變量,例子如下
int i = 1024, *p = &1; &r = i;
定義多個變量
在之前的例子中很容易認(rèn)為*和&作用于一個聲明語句的所有對象,其很大一個原因是我們可以將修飾符與變量名分開如下
int* p; //合法但是很容易造成誤解 int* p1, p2; //p1是一個指針,p2是一個整型 int *p1, *p2; //p1, p2都是指向整型的指針
指向指針的指針
通常來說,對于一個聲明符來說修飾符的數(shù)量并沒有限制,但有超過一個的修飾符時雖然符合邏輯,但是卻不總是很明晰,例如考慮一個指針,一個指針是內(nèi)存中的一個對象,所以我們可以將一個指針的地址存儲在一個指針中。
int ival = 1024; int *pi = &ival; //pi指向一個整型 int **ppi = π //ppi指向一個整型指針
指針的引用
由于引用不是一個對象,所以沒有指向引用的指針,但是指針是一個對象,所以有指向指針的引用
int i = 42; int *p1; //pi是一個整型指針 int *&r = p; //r是p的一個引用 r = &i; //r是p的引用,所以等同于p = &i *r = 0; //將i的值設(shè)置為0
最后
到此這篇關(guān)于C++入門教程之引用與指針的文章就介紹到這了,更多相關(guān)C++引用與指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C實(shí)現(xiàn)的非阻塞方式命令行端口掃描器源碼
這篇文章主要介紹了C實(shí)現(xiàn)的非阻塞方式命令行端口掃描器源碼,對于大家理解C端口掃描器有很大幫主,需要的朋友可以參考下2014-07-07C/C++實(shí)現(xiàn)Windows注冊表的基本操作
Windows注冊表(Registry)是Windows操作系統(tǒng)中用于存儲系統(tǒng)配置信息、用戶設(shè)置和應(yīng)用程序數(shù)據(jù)的一個集中式數(shù)據(jù)庫,本文主要為大家介紹了C++對注冊表的基本操作,感興趣的小伙伴可以了解下2023-11-11opencv配置的完整步驟(win10+VS2015+OpenCV3.1.0)
OpenCV是計(jì)算機(jī)視覺中經(jīng)典的專用庫,其支持多語言、跨平臺,功能強(qiáng)大,這篇文章主要給大家介紹了關(guān)于opencv配置(win10+VS2015+OpenCV3.1.0)的相關(guān)資料,需要的朋友可以參考下2021-06-06C++?Qt實(shí)現(xiàn)動態(tài)增加垂直滾動條
本博文源于筆者正在工作的一個小內(nèi)容,內(nèi)容涉及到為qt動態(tài)增加垂直滾動條,文章分為三個部分,問題起源,問題解決方案,問題解決成功效果,思路清晰,文章干貨滿滿,復(fù)制源碼即可使用,需要的朋友可以參考下2023-08-08