




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
上課請保持安靜!
請關閉您的手機!1C++大學基礎教程第6章指針和引用
北京科技大學信息基礎科學系2第六章指針和引用指針(Pointer)是C++和C的一種數據類型,
很多其他高級語言也有類似的數據類型;引用(Reference)則是C++所特有的一種數據類型本章將學習:指針和引用的概念;指針和引用的使用;動態內存的申請和刪除。3第六章指針和引用6.1指針的概念
6.2指針的運算6.3指針和函數(6.3.2和6.3.4不要求)6.4指針和字符串
6.5通過指針訪問數組(6.5.3和6.5.4不要求)6.6指針訪問動態內存6.7引用概念4本章教學要求:
掌握指針、指針變量、目標變量的基本概念;掌握指針變量的聲明和初始化,指針的運算;掌握指針作為函數的參數,指針和字符串的關系,指針和數組的關系;掌握void指針的應用,并能通過使用指針作為函數的參數;使用指針訪問字符串、一維數組和二維數組;使用指針訪問動態內存;掌握引用的聲明和使用。5上節內容回顧內存空間的訪問形式通過變量名直接訪問通過地址間接訪問指針、指針變量、目標變量指針變量的聲明和初始化6關于內存地址內存空間的訪問方式通過變量名直接訪問通過地址間接訪問取地址運算符:&例:int
var;則&var
表示變量var在內存中的起始地址7聲明例:
inti;
int*i_pointer=&i;
指向整型變量的指針指針變量的概念概念指針:變量的地址
用于間接訪問變量指針變量:
用于存放地址的變量目標變量:指針變量
存放的地址對應的變量20003i_pointer*i_pointeri2000變量
i_pointer內存用戶數據區變量i變量j362000200020043010引用例1:i=3;例2:*i_pointer=3;8小結幾個概念:指針,指針變量,目標變量符號*:在定義中表示變量為指針變量
int*i_pointer=&i;運算符:&:取地址運算符*:指向運算符
*i_pointer=3;9指針變量的定義和初始化語法形式
數據類型*指針名=初始地址;例:
inta;int*pa=&a;注意事項用變量地址作為初值時,該變量必須在指針初始化之前已說明過,且變量類型應與指針類型一致。可以用一個已賦初值的指針去初始化另一個指針變量。例:charch1=’Y’,ch2=’A’;char*pch1=&ch1,*pch2=&ch2;
char*pch3=pch2;10例1指針的概念#include<iostream.h>voidmain(){inta;
int*pa=&a;a=10;
cout<<"a:"<<a<<endl;
cout<<“*pa:"<<*pa<<endl;
cout<<“&a:"<<&a<<endl;
cout<<"pa:"<<pa<<endl;
cout<<"&pa:"<<&pa<<endl;}10a0012FF7Cpa0012FF780012FF7C內存用戶數據區11
6.2指針的運算
126.2指針的運算
表6.1指針的運算136.2.1指針的賦值運算
指針變量名=地址指針的賦值運算一定是地址的賦值。用來對指針變量賦值的可以是:同類型變量的地址;同類型的已經初始化的指針變量;其他同類型的指針。此外,也可以用0或者NULL對指針變量賦值。使得變量包含的是“空指針”,即不指向任何的內存物理地址。14指針的賦值運算“地址”中存放的數據類型與指針類型必須相符。必須注意:不同類型的指針是不可以互相賦值的。在指針賦值時,不存在類型自動轉換的機制。向指針變量賦的值必須是地址常量或變量,不能是普通整數。但可以賦值為整數0,表示空指針。15
例6.1觀察以下指針賦值運算的結果。如果將注釋去掉,結果將如何?#include<iostream>usingnamespacestd;voidmain(){intva1=100,*pva1;floatvf1=1.0,*pvf1,*pvf2;
int*pva2=NULL;
cout<<"valueofpva2is"<<pva2<<endl;pva1=&va1;pvf1=pvf2=&vf1;
cout<<pva1<<""<<&va1<<endl;
cout<<pvf1<<""<<pvf2<<endl;
cout<<&pva1<<endl;
cout<<&pvf1<<endl;
cout<<&pvf2<<endl;
//pvf1=pva1;}pvf20012FF6Cpvf10012FF70va11000012FF7Cpva10012FF78vf11.00012FF740012FF7C內存用戶數據區0012FF740012FF740pva20012FF6816例指針的定義、賦值與使用#include<iostream.h>voidmain(){ int*i_pointer; //聲明int型指針i_pointer
inti; //聲明int型數i i_pointer=&i; //取i的地址賦給i_pointer i=10; //int型數賦初值
cout<<"Outputinti="<<i<<endl;//輸出int型數的值
cout<<"Outputintpointeri="<<*i_pointer<<endl;//輸出int型指針所指地址的內容}176.2.2間接引用運算
間接引用運算符“*”是一種一元運算符,它和指針變量連用,對指針所指向的內存地址單元進行間接訪問。使用的格式是:
*指針變量如果指針變量iptr指向整型變量va,*iptr就是變量va的內容18
例6.2對變量的直接訪問和間接訪問:寫出以下程序運行結果。#include<iostream>usingnamespacestd;voidmain(){charch1='a',*ch;
intk1=100;
ch=&ch1; //指針ch指向變量ch1
cout<<"*ch="<<*ch<<endl; //間接訪問*ch='B';
cout<<"ch1="<<ch1<<endl; //直接訪問
ch1=k1;
cout<<"*ch="<<*ch<<endl; //間接訪問
}運行結果:*ch=ach1=B*ch=d19
例6.3定義指向指針的指針變量。觀察對這種指針變量間接訪問的結果。#include<iostream>usingnamespacestd;voidmain(){int
va=100,*pva,**ppva;
intk1=100;
pva=&va;
cout<<"*pva="<<*pva<<endl;
ppva=&pva;
cout<<"*ppva="<<*ppva<<endl;
cout<<"pva="<<pva<<endl; }運行結果:*pva=100*ppva=0x0012FF7C
pva=0x0012FF7C
va1000012FF7Cpva0012FF78ppva0012FF740012FF7C內存用戶數據區k10012FF701000012FF78206.2.2間接引用運算216.2.3指針的算術運算
指針可以進行的算術運算只有加法和減法。指針可以和一個整數n做加法或者減法運算。指針p和整數n相加(相減)的含義是指向當前指向位置p的前方或后方第n個數據的地址。22
例6.4通過指針的間接訪問,輸出下標為偶數的數組元素的值。#include<iostream>usingnamespacestd;voidmain(){intk1[10]={11,24,37,44,58,66,79,86,93,108},*k;k=&k1[0]; for(inti=0;i<10;i=i+2)
cout<<"k1["<<i<<"]="<<*(k+i)<<"";
cout<<endl;}
運行結果:K1[0]=11k1[2]=37….
數組第一個元素(下標為0)的地址賦值給指針k
每次循環,指針加2236.2.3指針的算術運算指針和指針的直接加法是沒有意義的,也是不允許的。指針和指針的減法是可以進行的,其意義是求出兩個指針之間可以存放幾個指定類型的數據。不允許用一個整數減一個指針。246.2.4指針的關系運算和邏輯運算
相同類型的指針可以進行各種關系運算。比較兩個指針相等還是不相等。進行指針“大于”、“小于”的比較,只是要判定指針在內存中的相對位置。
256.2.4指針的關系運算和邏輯運算指向不同數據類型的指針,指針和一般的整數比較是沒有意義的,也是不允許的。惟一可以和指針比較的整數是0。通過指針和0的比較來判定指針本身是不是空指針。即指針可以和零之間進行等于或不等于的關系運算。例如:p==0或p!=0指針可以進行“邏輯非”運算266.2.5void類型指針
void類型的指針就是“無類型”指針。聲明的方式如下: void*<指針名>;void類型的指針變量中存放的也是內存的地址,但是不指定這個地址單元內的數據的類型。27void類型指針的使用:任何其他類型的指針都可以賦值給void指針。必須注意,這樣賦值后的void指針的類型仍然是void。void類型指針不可以直接賦值給任何其他類型的指針。無論何時,void指針都不可以通過間接引用來訪問內存中的數據。28void類型指針的使用:要通過void類型指針訪問內存的數據,必須進行指針類型的強制轉換,才可以通過指針間接引用訪問內存數據。void類型指針一般不會獨立使用,而是作為指針類型轉換的中介:某種類型的指針
void指針,進行具體操作后強制轉換29memcpy函數函數原型:void*memcpy(void*dest,constvoid*src,
size_tcount);30
例6.5使用memcpy通用復制函數復制數組。
#include<iostream>usingnamespacestd;#include<string.h>voidmain(){charsrc[10]="012345678";chardest[10];char*pc=(char*)memcpy(dest,src,10);
cout<<pc<<endl;
ints1[3]={1,2,3};
intd1[3];
int*pi=(int*)memcpy(d1,s1,12);
cout<<*pi<<""<<*(pi+1)<<""<<*(pi+2)<<endl;}
運行結果:012345678123
復制字符數據,10個字節復制整型數據,12個字節316.2.5void類型指針
void類型指針還有一個具體的應用:顯示字符指針的內容。除了字符指針外,其他指針都可以直接用cout語句來輸出地址值。但是,用cout輸出字符指針時,則是輸出它所指向的字符串。可以將字符指針強制轉換為void指針,再用cout語句輸出,就可以看到地址值。如:char*pch="HelloC++";cout<<pch<<endl;cout<<(void*)pch<<endl;
inta[3]={1,2,3};cout<<a<<endl;cout<<*a<<endl;charc[]=“hello”;cout<<c<<endl;cout<<*c<<endl;cout<<c+1<<endl;cout<<(void*)c<<endl;326.3指針和函數
336.3指針和函數在程序設計中,指針有很多應用。其中之一就是用指針作為函數的參數,從而形成了C++函數調用中的另一種調用方式:地址調用。346.3.1指針作為函數的參數函數的形式參數是指針變量;函數的實參數是內存的地址,具體來說可以是數組名、變量的地址、用變量地址初始化的指針;形參指針類型和實參地址類型必須相同。用指針作為函數參數,實現地址調用,必須滿
足以下條件:356.3.1指針作為函數的參數實參傳遞給形參的是內存的地址,所以形參指針指向實參變量;形參指針通過間接引用,直接訪問實參變量,包括改變實參變量的值;函數調用后,可以保留對實參變量的操作結果,如果有多個實參,就可以有多個實參變量在函數調用中得到修改。滿足以上條件后,這樣的函數調用在使用上有
以下的特點:36
例6.6編寫數據交換的函數。在main中調用這個函數,交換main中定義的變量。
#include<iostream>usingnamespacestd;voidSwap(int*a,int*b);voidmain(){ intx(5),y(10);
cout<<"主函數變量的值:
x="<<x<<"y="<<y<<endl; Swap(&x,&y);
cout<<"返回后變量的值:
x="<<x<<"y="<<y<<endl;}voidSwap(int*a,int*b){ intt; t=*a; *a=*b; *b=t;
cout<<“函數中完成了交換:*a=“<<*a<<"*b="<<*b<<endl;}運行結果:主函數變量的值:x=5y=10函數中完成了交換:*a=10*b=5返回后變量的值:
x=10y=5
變量的地址作為實參數指針變量作為形式參數376.3.1指針作為函數的參數程序中用變量x和y的地址作實參,傳遞給指針a和b,如圖6.1(a)。通過間接引用*a和*b進行交換,實際上就是x和y進行交換,如圖6.1(b)。
38指針變量作為實參調用函數例6.7指針變量指向一個數組。用指針變量作為實參調用一個函數。在函數中指針指向數組的第二個元素。觀察函數返回后,實參指針值有無變化。39
#include<iostream>usingnamespacestd;voidMove(int*a);voidmain(){ intx[5]={10,20,30,40,50},*px=x;
cout<<"調用前的*px="<<*px<<endl;
Move(px);
cout<<"調用后的px"; if(px==x)cout<<"沒有變化,*px還是"<<*px<<endl; elsecout<<"也向前移動,*px變為"<<*px<<endl;}voidMove(int*a){ a=a+1;
cout<<"函數中完成了指針移動:*a="<<*a<<endl;}
運行結果:調用前的*px=10
函數中完成了指針移動:*a=20調用后的px沒有變化*px還是10
指針作為實參數指針變量作為形式參數406.3.3傳遞參數的保護:指針和常量通過數組名的地址調用,可以改變實參數組的內容。但是,并不是所有以數組名作為實參的函數調用,都需要改變數組的值。例如,在調用一個求數組最大值的函數時,就不希望數組的值發生變化。希望在函數中能夠限制對數組元素的修改。使用常指針可以達到這個目的。416.3.3傳遞參數的保護:指針和常量常指針是指向常量的指針(PointertoConstantdata)的習慣說法。就是規定指針所指向的內容不可以通過指針的間接引用來改變。常指針說明的格式是:
const<類型名>*<指針名>;
例如:constint*ptint;
指針ptint的類型是(constint*),也就是指向一個恒定的整型數。42
例6.10常指針示例。觀察以下程序的運行。
#include<iostream>usingnamespacestd;voidmain(){int
ia=10,ib=20;constint*ptint; ptint=&ia; //用ia地址初始化cout<<*ptint<<endl;ptint=&ib; //改變為ib的地址ib=ib+100; //ib本身仍然可以改變cout<<*ptint<<endl;//*ptint=100;
//語句錯誤:左值是常量}
運行結果:10
120常指針聲明注釋去掉會出現編譯錯誤436.3.3傳遞參數的保護:指針和常量指針常量(Pointerconstant)。指針本身的內容是個常量,不可以改變。指針常量聲明的格式是:
<類型名>*const<指針名>=<初值>;例如: charch,*constptch=&ch;
數組名就是數組的首地址。現在可以說:數組名就是一個指針常量。
44
例6.11指針常量示例。指出以下程序的錯誤。#include<iostream>usingnamespacestd;voidmain()
{inta=10,b=100;
int*constpa=&a; //pa是指針常量
cout<<*pa<<endl; *pa=20; //指針常量的間接引用是允許的
cout<<a<<endl; pa=&b;
constintc=50;// int*constpc=&c; }
錯誤語句注釋掉后運行結果:10
20語句有錯:常量不能當左值語句有錯,地址類型不同//45
例6.12用常指針作形參,函數printString可以輸出數組的內容,不可以對數組修改。
#include<iostream>usingnamespacestd;voidprintString(constchar*);voidmain(){charphrase[]="C++isamodernprogramminglanguage";
cout<<"Thestringis:\n";
printString(phrase);
cout<<endl;}voidprintString(constchar*Ptarray){while(*Ptarray) {//*Ptarray=*Ptarray+1;
cout<<*Ptarray++;} }不使用常指針也是可以完成打印。但是沒有保護了。數組名作實參數常指針作形式參數466.4指針和字符串
476.4.1字符串處理的兩種方式C++字符串常量是用雙引號括起的字符序列,并以字符‘\0’作為結束標志。如
"Thisisastring"。字符串常量存放在內存的某個區域,有自己固定的首地址。如果將字符串常量的首地址看成是指針,這種指針既是常指針,也是指針常量。486.4.1字符串處理的兩種方式C++處理字符串有兩種方式:數組方式和指針方式。數組方式是將字符串存入字符數組后,再進行處理。一般可以在聲明數組的時候用字符串來初始化:charstring_array[]="aniceday!";指針方式是用字符串常量來初始化一個字符指針:char*string_pt="aniceday!";496.4.1字符串處理的兩種方式常量不能放在等式左邊運行時會出錯50
例6.14strcpy和strncpy的比較。#include<iostream>#include<string>usingnamespacestd;voidmain(){intn;char*array1="HappyBirthdaytoYou";chararray3[15];chararray2[25];
strcpy(array2,array1);
cout<<"Thestringinarray1is:"<<array1<<"\nThestringinarray2is:"<<array2<<'\n';/*strcpy(array3,array1);
cout<<array3<<endl;*/n=sizeof(array3);
strncpy(array3,array1,n-1);//復制array1n-1個字符到array3array3[14]='\0'; //添加'\0'到array3
cout<<"Thestringinarray3is:"<<array3<<endl;}不包括提示的運行結果HappyBirthdaytoYouHappyBirthdaytoYouHappyBirthday
復制array1到array2,沒有問題復制array1到array3,空間不夠,有運行錯誤按實際數組大小,復制array1到array3,沒有問題516.5通過指針訪問數組
526.5通過指針訪問數組指針和數組有天然的聯系。因為數組名本身就是地址,也就是某種類型的指針。將指針和數組名聯系起來,訪問數組就多了一種方法。雖然一維數組名和二維數組名都是地址,都可以看作是某種指針,但是指針的類型是不同的。因此,通過指針訪問一維數組和二維數組的方法是不同的。
536.5.1通過指針訪問一維數組要通過指針訪問一維數組,必須首先聲明一個和數組類型相同的指針,并且用數組名來對指針初始化,如:
intA[10],*pa=A;然后,就可以用多種方式訪問數組元素:數組名和下標,如A[0]、A[4];指針和下標,如pa[0]、pa[4];指針加偏移量的間接引用,如*(pa+4);數組名加偏移量的間接引用,如*(A+4);指針自加后的間接引用,如*pa++。
54
例6.15求數組內所存放的字符串的長度。#include<iostream>usingnamespacestd;voidmain(){charChArray[]="Thisisastring.",*ptch;
inti,j,k,offset1,offset2;
ptch=ChArray; //指針初始化
for(i=0;ChArray[i]!='\0';i++);
cout<<"Thelengthofthestringis:"<<i<<endl;
for(j=0;ptch[j]!='\0';j++);
cout<<"Thelengthofthestringis:"<<j<<endl;
for(offset1=0;*(ChArray+offset1)!='\0';offset1++);
cout<<"Thelengthofthestringis:"<<offset1<<endl;
for(offset2=0;*(ptch+offset2)!='\0';offset2++);
cout<<"Thelengthofthestringis:"<<offset2<<endl;
for(k=0;*ptch++!='\0';k++);
cout<<"Thelengthofthestringis:"<<k<<endl;}
運行結果都相同方式1:數組名和下標方式2:指針和下標方式3:數組名加偏移量的間接引用方式4:指針加偏移量的間接引用方式5:指針自加的間接引用55
例6.16求整型數組的平均值,顯示數組元素和平均值。#include<iostream>usingnamespacestd;voidmain(){int
intArray[10]={8,11,23,34,45,56,65,78,86,97},*ptint;
inti,num,sum;floataverage;
ptint=intArray;
sum=0;num=sizeof(intArray)/sizeof(*intArray);
for(i=0;i<num;i++)sum=sum+*ptint++;average=(float)sum/num;
ptint=intArray;
cout<<"數組元素是:\n";
for(i=0;i<num;i++)
cout<<*ptint++<<"";
cout<<"\n平均值是:"<<average<<endl;}
數組元素是:8112334455665788697平均值是:50.3
指針初始化求數組元素的數目求平均值指針再次初始化輸出數組元素和它們的平均值566.5.2通過指針訪問二維數組二維數組可以看成是一維數組的一維數組。二維數組名雖然也是地址(指針),但是卻和一維數組名有不同的類型。對一維數組A[5],數組名A的地址,就是數組第一個元素A[0]的地址。指針的類型是指向數組元素的指針。A+1就是元素A[1]的地址。576.5.2通過指針訪問二維數組對二維數組B[3][4],數組名B的地址,則是其中第一個一維數組B[0]的地址。指針的類型是指向一維數組的指針。B+1就是下一個一維數組B[1]的地址。如圖6.3所示。
586.5.2通過指針訪問二維數組在定義指向一維數組的指針時,還必須指出一維數組的大小。聲明指向一維數組的指針的格式如下: <類型名>(*指針變量名)[一維數組大小];
例如,和圖6.3中兩個二維數組所對應的指向一維數組的指針定義如下:char(*ptchb)[4],(*ptchc)[2];ptchb=B;ptchc=C;596.5.2通過指針訪問二維數組對于指向一維數組的指針,具有以下的特征:
二維數組名是指向一維數組的指針,而不是指向數組元素的指針。
指向一維數組指針加1的結果,是指向下一個一維數組的指針。
指向一維數組的指針的間接引用的結果仍然是地址,即*ptchb仍然是地址。只是地址的類型變了。變為一維數組B[0]第一個元素B[0][0]的地址。
因為*ptchb是數組元素的地址,**ptchb就是數組元素的值。用指向一維數組指針訪問二維數組第i行第j列元素的一般公式是*(*(指針名+i)+j)。
60指向一維數組的指針ptchbptchbB[0]的地址*ptchbB[0][0]的地址**ptchbB[0][0]的值*(指針名+i)B[i][0]的地址*(*(指針名+i)+j)B[i][j]的值61
例6.17比較指向一維數組的指針和指向數組元素的指針。#include<iostream>usingnamespacestd;voidmain(){shortB[3][4],C[3][2];short(*ptshb)[4],(*ptshc)[2];
ptshb=B;ptshc=C;
cout<<"比較不同的指向一維數組指針的差別\n";
cout<<"ptshb的地址是:"<<ptshb<<"\n";
cout<<"ptchb+1的地址是:"<<ptshb+1<<"\n";
cout<<"ptchc的地址是:"<<ptshc<<"\n";
cout<<"ptchc+1的地址是:"<<ptshc+1<<"\n";
比較不同的指向一維數組指針的差別ptshb的地址是:0x0012FF68ptchb+1的地址是:0x0012FF70ptchc的地址是:0x0012FF5Cptchc+1的地址是:0x0012FF60
B的第0行地址
B的第1行地址
C的第0行地址
C的第1行地址62
例6.17比較指向一維數組的指針和指向數組元素的指針。
cout<<"不同類型的指針\n";
cout<<"ptshb的地址是:"<<ptshb<<endl;
cout<<"*ptshb的地址是:"<<*ptshb<<endl;
cout<<"*ptshb+1的地址是:"<<*ptshb+1<<endl;
cout<<"B[0][1]的地址是:"<<&B[0][1]<<endl;//cout<<"ptchb和*ptchb相等嗎?"<<(ptchb==*ptchb)<<endl; //有語法錯誤
cout<<"*ptshb+1和&B[0][1]相等嗎?";
if(*ptshb+1==&B[0][1])cout<<"Yes"<<endl;}
不同類型的指針ptshb的地址是:0x0012FF68*ptshb的地址是:0x0012FF68*ptshb+1的地址是:0x0012FF6AB[0][1]的地址是:0x0012FF6A*ptshb+1和&B[0][1]相等嗎?Yes
B的第0行地址
B的第0行第0列元素的地址
B的第0行第1列元素的地址
B的第0行第1列元素的地址063
例6.18用單循環程序,求二維數組元素的平均值。#include<iostream>usingnamespacestd;voidmain(){int
dArray[3][4]={32,42,12,25,56,76,46,53,76,89,96,82},(*pt)[4];
intsum,j;floataverage;sum=0;pt=dArray;
j=sizeof(dArray)/sizeof(**dArray); for(inti=0;i<j;i++) sum=sum+*(*pt+i);average=(float)sum/j;
cout<<"數據的平均值等于:"<<average<<endl;}
運行結果:數據的平均值等于57.0833指向一維數組指針的初始化求數組元素的數目,**dArray就是元素dArray[0][0]數組求和求平均值輸出平均值646.6指針訪問動態內存656.6指針訪問動態內存
動態內存是在程序執行時才可以申請、使用和釋放的內存。也就是存放動態數據的內存區域。存放動態數據的區域稱為“堆”,動態內存也稱為堆內存。動態內存不能通過變量名來使用,而只能通過指針來使用。666.6.1動態內存的申請和釋放C++中通過運算符new申請動態內存,運算符delete釋放動態內存。動態內存申請運算符new的使用格式:
new<類型名>(初值)運算的結果:如果申請成功,返回指定類型內存的地址;如果申請失敗,返回NULL指針。int*pi;pi=newint(10);動態內存使用完畢后,要用delete運算來釋放。delete運算符使用格式:
delete<指針名>;
676.6.2動態數組空間的申請和釋放申請動態一維數組時,要在new表達式中加上申請數組的大小:new<類型名>[常量表達式];注意:在動態申請數組空間時,不可以對數組進行初始化。申請一個動態的整型數組:
int*piarray;
piarray=newint[10];也可以申請二維數組的空間:
int(*pi_marray)[4];pi_marray=newint[3][4];釋放動態數組空間都用相同的表達式:delete[]<指針名>;
686.6.3內存泄漏和指針懸掛
內存泄漏是指動態申請的內存空間,沒有正常釋放,但是也不能繼續使用的情況。如:char*ch1;ch1=newchar('A');char*ch2=newchar;ch1=ch2;原來為ch1所申請的存放字符A的空間就不可能再使用了,產生了內存泄漏。696.6.3內存泄漏和指針懸掛讓指針指向一個已經釋放的空間,即所謂的指針懸掛(Dangling)。如:char*ch1,*ch2;ch1=newchar;ch2=ch1;*ch2='B';deletech1;指針ch2就是指向了一個已經釋放的地址空間,形成指針懸掛。如果還要用deletech2;語句來釋放ch2所指向的空間,就會出現運行錯誤。706.7引用概念716.7引用概念引用(Reference)是C++中新引入的概念,也是C語言中不存在的數據類型。
引用是變量或者其他編程實體(如對象)的別名。因此,引用是不可以單獨定義的。如圖6.4(a)所示,變量A在內存中有自己的地址,而A的引用B實際上就是變量A,只是A的另外一個名字。
726.7.1引用的聲明和使用引用是通過運算符&來定義的,定義的格式如下:
<類型名>&引用名=變量名;其中的變量名必須是已經定義的,并且和引用的類型必須相同。例如:
int
someInt;
int&refInt=someInt;必須注意:引用必須在聲明的時候就完成初始化,不可以先聲明引用,然后再用另一個語句對它初始化。
736.7.1引用的聲明和使用引用有以下的特點:引用不能獨立存在,它只是其他變量的別名;引用必須在聲明的同時就初始化;引用一旦定義,引用關系就不可以更改,即B若是A的引用,就不可能是其他變量的引用;引用的類型就是相關的變量的類型,引用的使用和變量的使用相同。74
例6.22引用的使用。觀察以下程序的結果。
#include<iostream>usingnamespacestd;voidmain(){int
intA=10;
int&refA=intA;
cout<<"引用的值和相關變量值相同:refA="<<refA<<endl;
refA=5;
cout<<"引用的變化,則相關變量也變化:intA="<<intA<<endl;
cout<<"引用的地址和相關變量地址相同:intA的地址="<<&intA<<endl;
cout<<"引用的地址和相關變量地址相同:refA的地址="<<&refA<<endl;}引用的值和相關變量值相同:refA=10引用的變化,則相關變量也變化:intA=5引用的地址和相關變量地址相同:intA的地址=0x0012FF7C引用的地址和相關變量地址相同:refA的地址=0x0012FF7C756.7.1常引用如果不希望通過引用來改變相關的變量的值,則可以定義常引用。常引用定義的格式:
const<類型名>&引用名=變量名;例如:int
someInt=10;constint&const_refA=someInt;例如:const_refA=50;
此時,const_refA就是常引用。不可以通過const_refA來改變someInt變量的值。76
例6.23指針的引用。
#include<iostream>usingnamespacestd;voidmain(){int
intA=10,intB=20;
int*pti=&intA;
int*&refi=pti;
cout<<"指針的引用可以訪問指針所指的變量:*refi="<<*refi<<endl;
cout<<"指針變量原來的值:pti="<<pti<<endl;
refi=&intB;
cout<<"引用的變化,則相關指針也變化:pti="
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 土工墊塊銷售方案(3篇)
- 物品寄售服務方案(3篇)
- 淮陰工學院《口腔預防醫學》2023-2024學年第二學期期末試卷
- 江西工業職業技術學院《外國音樂史與作品欣賞》2023-2024學年第二學期期末試卷
- 被子翻新改造方案(3篇)
- 山東省聊城市第一實驗學校2024-2025學年高一下學期第二次學情檢測數學試卷(含答案)
- 家具投標服務方案(3篇)
- 慰問物資投標方案(3篇)
- 保潔施工方案(3篇)
- 項目投資策劃方案(3篇)
- 北京理工附中小升初分班考試真題
- 膀胱鏡檢查記錄
- 英語社團活動課件
- 第三方檢測市場部管理制度提成方案
- 學前兒童發展心理學-情感
- 二年級下冊數學教案 《生活中的大數》練習課 北師大版
- GB∕T 16762-2020 一般用途鋼絲繩吊索特性和技術條件
- 電網施工作業票模板
- T∕CAEPI 31-2021 旋轉式沸石吸附濃縮裝置技術要求
- 國家級高技能人才培訓基地建設項目實施管理辦法
- 彩盒成品檢驗標準
評論
0/150
提交評論