版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
2025/10/91C++高級(jí)語言程序設(shè)計(jì)第6章指針和引用
北京郵電大學(xué) 信息與通信工程學(xué)院北京郵電大學(xué)信息與通信工程學(xué)院指針(Pointer)是C++和C的一種數(shù)據(jù)類型。很多其他高級(jí)語言也有類似的數(shù)據(jù)類型。引用(Reference)則是C++所特有的一種數(shù)據(jù)類型。指針和引用在概念上和使用上都有相似之處,但是也有重要的差別。2025/10/9-2-北京郵電大學(xué)信息與通信工程學(xué)院第六章指針和引用6.1指針的概念6.2指針的運(yùn)算6.3指針訪問動(dòng)態(tài)內(nèi)存6.4指向結(jié)構(gòu)體的指針6.5引用概念6.6指針和引用作為函數(shù)的參數(shù)6.7指針和引用作為函數(shù)的返回值6.8指針和字符串6.9通過指針訪問數(shù)組2025/10/9-3-北京郵電大學(xué)信息與通信工程學(xué)院6.1指針的概念
2025/10/94北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-5-6.1.1
指針和指針變量指針是變量的地址?;蛘哒f是在內(nèi)存中,存放某種類型變量的地址。例如,定義了整型變量a,a的地址就是一個(gè)指針。也可以不定義任何變量,只是指定內(nèi)存某個(gè)地址開始(如0x00430100)的4個(gè)字節(jié)存放整型變量,這樣的地址也是指針。存放指針的變量就是指針變量。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-6-6.1.1
指針和指針變量當(dāng)聲明了一個(gè)指針變量后,確定了三件事:變量本身在內(nèi)存中所分配的地址和字節(jié)數(shù),指針變量總是占有4個(gè)字節(jié);系統(tǒng)允許的地址范圍,以及地址單元內(nèi)可以存放的內(nèi)容;指針變量可以進(jìn)行的運(yùn)算。訪問指針變量時(shí),只能看到地址。只有通過這個(gè)地址,才能訪問地址單元中的內(nèi)容。這樣的訪問稱為對(duì)于內(nèi)存單元的間接訪問。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-7-6.1.2指針變量的聲明和初始化指針變量聲明的格式是:
<類型名>*變量名1,*變量名2;例如:
int*va1,*va2; char*ch1,*ch2;指針變量在聲明后,變量的值(地址)是隨機(jī)的。這樣的指針變量是不能安全的使用的。因?yàn)槠渲械碾S機(jī)地址完全可能不是有效的數(shù)據(jù)地址。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-8-6.1.2指針變量的聲明和初始化在聲明指針變量時(shí)的“*”,有兩個(gè)含義:聲明變量va1、va2、ch1、ch2都是指針變量;說明變量va1和va2的類型是(int*)型,即指向整型變量的指針。va1和va2所指定的地址單元中,只能存放整型數(shù)據(jù)。類似地,ch1和ch2的類型是(char*)型,它們所指定的地址單元中,只能存放字符。指針變量都是有類型的.指針變量的類型就是它所指定的地址單元中存放的數(shù)據(jù)的類型。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-9-6.1.2指針變量的聲明和初始化指針變量的初始化有兩種方法:在聲明時(shí)的初始化和聲明后的初始化。聲明指針變量時(shí)就進(jìn)行初始化的格式是:
<類型名>*指針變量名=&變量名;其中的變量名應(yīng)該是已經(jīng)聲明或定義的同類型變量名。例如:
charch1=’Y’,ch2=’A’; char*pch1=&ch1,*pch2=&ch2;2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-10-6.1.2指針變量的聲明和初始化也可以在聲明指針變量后,用賦值的方式對(duì)它們進(jìn)行初始化。例如:
inti1=’Y’,i2=’A’; int*pi1,*pi2; pi1=&i1; pi2=&i2;沒有初始化指針變量是不可以使用的。編譯帶有這樣的指針變量的程序,編譯系統(tǒng)會(huì)給出警告,而運(yùn)行時(shí)會(huì)出現(xiàn)錯(cuò)誤。
6.2指針的運(yùn)算
2025/10/9-11-北京郵電大學(xué)信息與通信工程學(xué)院6.2指針的運(yùn)算表6.1指針的運(yùn)算2025/10/9-12-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-13-6.2.1指針的賦值運(yùn)算指針的賦值運(yùn)算一定是地址的賦值。用來對(duì)指針變量賦值的可以是:同類型變量的地址;同類型的已經(jīng)初始化的指針變量;其他同類型的指針。此外,也可以用0或者NULL對(duì)指針變量賦值。使得變量包含的是“空指針”,即不指向任何的內(nèi)存物理地址。必須注意:不同類型的指針是不可以互相賦值的。在指針賦值時(shí),不存在類型自動(dòng)轉(zhuǎn)換的機(jī)制。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-14-
例6.1觀察以下指針賦值運(yùn)算的結(jié)果。如果將注釋去掉,結(jié)果將如何?#include<iostream>usingnamespacestd;voidmain(){intva1=100,*pva1;floatvf1='A',*pvf1,*pvf2;int*pva2=NULL;cout<<"valueofpva1is"<<pva2<<endl;pva1=&va1;pvf1=pvf2=&vf1;cout<<pva1<<""<<&va1<<endl;cout<<pvf1<<""<<pvf2<<endl;//pvf1=pva1;}valueofpva1is0x000000000x0012FF7C0x0012FF7C0x0012FF740x0012FF74注釋去掉會(huì)出現(xiàn)編譯錯(cuò)誤2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-15-6.2.2間接引用運(yùn)算
間接引用運(yùn)算符“*”是一種一元算符,它和指針變量連用,對(duì)指針?biāo)赶虻膬?nèi)存地址單元進(jìn)行間接訪問。使用的格式是:
*指針變量如果指針變量iptr指向整型變量va,*iptr就是變量va的內(nèi)容2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-16-
例6.2對(duì)變量的直接訪問和間接訪問:寫出以下程序運(yùn)行結(jié)果。#include<iostream>usingnamespacestd;voidmain(){charch1='a',*ch;intk1=100;ch=&ch1; //指針ch指向變量ch1cout<<"*ch="<<*ch<<endl; //間接訪問*ch='B';cout<<"ch1="<<ch1<<endl; //直接訪問
ch1=k1;cout<<"*ch="<<*ch<<endl; //間接訪問
}運(yùn)行結(jié)果:*ch=ach1=B*ch=d2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-17-
例6.3定義指向指針的指針變量。觀察對(duì)這種指針變量間接訪問的結(jié)果。#include<iostream>usingnamespacestd;voidmain(){intva=100,*pva,**ppva;//ppva是指向指針的指針
intk1=100;pva=&va;cout<<"*pva="<<*pva<<endl; //間接訪問結(jié)果是整型數(shù)
ppva=&pva;cout<<"*ppva="<<*ppva<<endl;//間接訪問結(jié)果是地址
cout<<"pva="<<pva<<endl; //就是指針pva的內(nèi)容}運(yùn)行結(jié)果:*pva=100*ppva=0x0012FF7Cpva=0x0012FF7C
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-18-6.2.2間接引用運(yùn)算2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-19-6.2.3指針的算術(shù)運(yùn)算
指針可以進(jìn)行的算術(shù)運(yùn)算只有加法和減法。指針可以和一個(gè)整數(shù)n做加法或者減法運(yùn)算。指針p和整數(shù)n相加(相減)的含義是指向當(dāng)前指向位置p的前方或后方第n個(gè)數(shù)據(jù)的地址。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-20-
例6.3通過指針的間接訪問,輸出下標(biāo)為偶數(shù)的數(shù)組元素的值。#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;}
運(yùn)行結(jié)果:K1[0]=11k1[2]=37….
數(shù)組第一個(gè)元素(下標(biāo)為0)的地址賦值給指針k
每次循環(huán),指針加22025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-21-6.2.3指針的算術(shù)運(yùn)算指針和指針的直接加法是沒有意義的,也是不允許的。指針和指針的減法是可以進(jìn)行的,其意義是求出兩個(gè)指針之間可以存放幾個(gè)指定類型的數(shù)據(jù)。不允許用一個(gè)整數(shù)減一個(gè)指針。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-22-6.2.4指針的關(guān)系運(yùn)算和邏輯運(yùn)算
相同類型的指針可以進(jìn)行各種關(guān)系運(yùn)算。比較兩個(gè)指針相等還是不相等。進(jìn)行指針“大于”、“小于”的比較,只是要判定指針在內(nèi)存中的相對(duì)位置。指針和一般的整數(shù)比較是沒有意義的,也是不允許的。惟一可以和指針比較的整數(shù)是0。通過指針和0的比較來判定指針本身是不是空指針。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-23-6.2.5void類型指針
void類型的指針就是“無類型”指針。聲明的方式如下: void*<指針名>;void類型的指針變量中存放的也是內(nèi)存的地址,但是不指定這個(gè)地址單元內(nèi)的數(shù)據(jù)的類型。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-24-6.2.5void類型指針
void類型的指針的使用:任何其他類型的指針都可以賦值給void指針。必須注意,這樣賦值后的void指針的類型仍然是void。void類型指針不可以直接賦值給任何其他類型的指針。無論何時(shí),void指針都不可以通過間接引用來訪問內(nèi)存中的數(shù)據(jù)。要通過void類型指針訪問內(nèi)存的數(shù)據(jù),必須進(jìn)行指針類型的強(qiáng)制轉(zhuǎn)換,才可以通過指針間接引用訪問內(nèi)存數(shù)據(jù)。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-25-void類型指針
void類型指針還有一個(gè)具體的應(yīng)用:顯示字符指針的內(nèi)容。除了字符指針外,其他指針都可以直接用cout語句來輸出地址值。但是,用cout輸出字符指針時(shí),則是輸出它所指向的字符串??梢詫⒆址羔槒?qiáng)制轉(zhuǎn)換為void指針,再用cout語句輸出,就可以看到地址值。如:char*pch="HelloC++";cout<<pch<<endl;cout<<(void*)pch<<endl;
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-26-
例6.4
使用memcpy通用復(fù)制函數(shù)復(fù)制數(shù)組。
#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;}
運(yùn)行結(jié)果:012345678123
復(fù)制字符數(shù)據(jù),10個(gè)字節(jié)復(fù)制整型數(shù)據(jù),12個(gè)字節(jié)2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-27-6.2.6指針類型轉(zhuǎn)換實(shí)際應(yīng)用的指針變量都是有類型的,指針類型就是指針?biāo)傅牡刂房臻g所存放的數(shù)據(jù)的類型。除了void指針,不同類型的指針是不可以自動(dòng)類型轉(zhuǎn)換的,也就不能進(jìn)行賦值運(yùn)算。在例6-1中的語句pvf1=pva1(整型指針賦值給float指針)就是有語法錯(cuò)誤的語句。指針類型不僅不能自動(dòng)轉(zhuǎn)換,也不能進(jìn)行強(qiáng)制類型轉(zhuǎn)換。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-28-指針類型轉(zhuǎn)換若pch是字符指針,p是double類型指針,以下的語句:
pch=static_cast<char*>(p);在編譯時(shí)有語法錯(cuò)誤:“不能將double*轉(zhuǎn)換為char*”,也就是說指針的強(qiáng)制類型轉(zhuǎn)換也是不允許的。但是,如果使用C風(fēng)格的類型轉(zhuǎn)換:pch=(char*)p;在編譯時(shí)沒有語法錯(cuò)誤,僅在執(zhí)行時(shí)有問題。所以,還是要使用static_cast來進(jìn)行強(qiáng)制類型轉(zhuǎn)換。唯一允許的是void指針和其它指針類型之間的轉(zhuǎn)換2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-29-//例6-5利用格式控制符hex可以顯示整數(shù)的機(jī)器數(shù)的程序#include<iostream>usingnamespacestd;voidmain() floatf=1.0; float*fPtr=&f;//浮點(diǎn)指針
void*fv=&f; int*iPtr=static_cast<int*>(fv); //浮點(diǎn)變量地址賦給整型指針
cout<<f<<endl <<"iPtr:"<<iPtr<<"=>"<<*iPtr <<"=>"<<hex<<*iPtr<<endl <<"fPtr:"<<fPtr<<"=>"<<*fPtr<<endl;} 6.3指針訪問動(dòng)態(tài)內(nèi)存2025/10/9-30-北京郵電大學(xué)信息與通信工程學(xué)院指針訪問動(dòng)態(tài)內(nèi)存
動(dòng)態(tài)內(nèi)存是在程序執(zhí)行時(shí)才可以申請(qǐng)、使用和釋放的內(nèi)存。也就是存放動(dòng)態(tài)數(shù)據(jù)的內(nèi)存區(qū)域。存放動(dòng)態(tài)數(shù)據(jù)的區(qū)域稱為“堆”,動(dòng)態(tài)內(nèi)存也稱為堆內(nèi)存。動(dòng)態(tài)內(nèi)存不能通過變量名來使用,而只能通過指針來使用。2025/10/9-31-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-32-6.3.1動(dòng)態(tài)內(nèi)存的申請(qǐng)和釋放C++中通過運(yùn)算符new申請(qǐng)動(dòng)態(tài)內(nèi)存,運(yùn)算符delete釋放動(dòng)態(tài)內(nèi)存。動(dòng)態(tài)內(nèi)存申請(qǐng)運(yùn)算符new的使用格式:
new<類型名>(初值)運(yùn)算的結(jié)果:如果申請(qǐng)成功,返回指定類型內(nèi)存的地址;如果申請(qǐng)失敗,返回NULL指針。動(dòng)態(tài)內(nèi)存使用完畢后,要用delete運(yùn)算來釋放。delete運(yùn)算符使用格式:
delete<指針名>;
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-33-6.3.2動(dòng)態(tài)數(shù)組空間的申請(qǐng)和釋放申請(qǐng)動(dòng)態(tài)一維數(shù)組時(shí),要在new表達(dá)式中加上申請(qǐng)數(shù)組的大?。簄ew<類型名>[常量表達(dá)式];注意:在動(dòng)態(tài)申請(qǐng)數(shù)組空間時(shí),不可以對(duì)數(shù)組進(jìn)行初始化。也可以申請(qǐng)二維數(shù)組的空間:int(*pi_marray)[4];pi_marray=newint[3][4];釋放動(dòng)態(tài)數(shù)組空間都用相同的表達(dá)式:delete[]<指針名>;
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-34-6.3.3內(nèi)存泄漏和指針懸掛
內(nèi)存泄漏是指動(dòng)態(tài)申請(qǐng)的內(nèi)存空間,沒有正常釋放,但是也不能繼續(xù)使用的情況。如:char*ch1;ch1=newchar('A');char*ch2=newchar;ch1=ch2;原來為ch1所申請(qǐng)的存放字符A的空間就不可能再使用了,產(chǎn)生了內(nèi)存泄漏。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-35-6.3.3內(nèi)存泄漏和指針懸掛讓指針指向一個(gè)已經(jīng)釋放的空間,即所謂的指針懸掛(Dangling)。如:char*ch1,*ch2;ch1=newchar;ch2=ch1;*ch2='B';deletech1;指針ch2就是指向了一個(gè)已經(jīng)釋放的地址空間,形成指針懸掛。如果還要用deletech2;語句來釋放ch2所指向的空間,就會(huì)出現(xiàn)運(yùn)行錯(cuò)誤。6.4指向結(jié)構(gòu)體的指針2025/10/9-36-北京郵電大學(xué)信息與通信工程學(xué)院
指向結(jié)構(gòu)體的指針定義變量時(shí),我們可以定義指向int型的指針變量,類似的,可以有指向新定義的結(jié)構(gòu)型數(shù)據(jù)類型的指針變量。聲明了指向結(jié)構(gòu)的指針后,必須對(duì)指針初始化。現(xiàn)在我們知道對(duì)于指針的初始化有兩種方法:其一是用已經(jīng)定義的變量地址來初始化,其二是用new申請(qǐng)一個(gè)地址來對(duì)指針賦值。2025/10/9-37-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-38-具體對(duì)結(jié)構(gòu)指針來說:(1)可以將結(jié)構(gòu)變量的地址賦給結(jié)構(gòu)指針,使用取地址“&”操作,得到結(jié)構(gòu)變量的地址,這個(gè)地址就是結(jié)構(gòu)的第一個(gè)成員的地址。例如:structstudent //聲明新的數(shù)據(jù)類型{longnum; //學(xué)號(hào)
charname[20]; //姓名
floatscore; //成績(jī)};studentstu={20041118,"LiLi",'F',18}; //定義結(jié)構(gòu)變量并初始化student*ps=&stu; //定義結(jié)構(gòu)指針并初始化2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-39-(2)使用new操作在堆中給結(jié)構(gòu)指針分配空間。例如: student*ps=newstudent; //定義結(jié)構(gòu)指針用動(dòng)態(tài)地址初始化
用結(jié)構(gòu)指針訪問結(jié)構(gòu)成員時(shí),用箭頭操作符代替原來的點(diǎn)操作符對(duì)結(jié)構(gòu)體成員進(jìn)行操作。比如,把學(xué)生的成績(jī)輸出顯示,語句如下: cout<<ps->score;
其中,ps->score等價(jià)于(*ps).score。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-40-解:說明:每個(gè)員工的信息包括姓名、工作證號(hào)、薪水,定義為結(jié)構(gòu)類型。定義結(jié)構(gòu)指針并讓它的指向確定,通過結(jié)構(gòu)指針訪問結(jié)構(gòu)成員,輸出顯示員工的信息。//例6-6結(jié)構(gòu)指針的定義和使用#include<iostream>#include<string>usingnamespacestd;structEmployee{charname[20];unsignedlongid;floatsalary;};例6-6結(jié)構(gòu)指針的定義和使用。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-41-voidmain(){Employeepr1;Employee*prPtr;prPtr=&pr1;strcpy(prPtr->name,"zhangsan");prPtr->id=98001;prPtr->salary=3350.0;cout<<prPtr->name<<""<<prPtr->id<<""<<prPtr->salary<<endl;}程序運(yùn)行結(jié)果:zhangsan9800133506.5引用概念2025/10/9-42-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-43-引用概念引用(Reference)是C++中新引入的概念,也是C語言中不存在的數(shù)據(jù)類型。
引用是變量或者其他編程實(shí)體(如對(duì)象)的別名。因此,引用是不可以單獨(dú)定義的。如圖6.4(a)所示,變量A在內(nèi)存中有自己的地址,而A的引用B實(shí)際上就是變量A,只是A的另外一個(gè)名字。
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-44-6.5.1引用的聲明引用是通過運(yùn)算符&來定義的,定義的格式如下:
<類型名>&引用名=變量名;其中的變量名必須是已經(jīng)定義的,并且和引用的類型必須相同。例如:
intsomeInt; int&refInt=someInt;必須注意:引用必須在聲明的時(shí)候就完成初始化,不可以先聲明引用,然后再用另一個(gè)語句對(duì)它初始化。
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-45-引用有以下的特點(diǎn):引用不能獨(dú)立存在,它只是其他變量的別名;引用必須在聲明的同時(shí)就初始化;引用一旦定義,引用關(guān)系就不可以更改,即B若是A的引用,就不可能是其他變量的引用;引用的類型就是相關(guān)的變量的類型,引用的使用和變量的使用相同。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-46-
例6-7引用的使用。觀察以下程序的結(jié)果。
#include<iostream>usingnamespacestd;voidmain(){intintA=10;int&refA=intA;cout<<"引用的值和相關(guān)變量值相同:refA="<<refA<<endl;refA=5;cout<<"引用的變化,則相關(guān)變量也變化:intA="<<intA<<endl;cout<<"引用的地址和相關(guān)變量地址相同:intA的地址="<<&intA<<endl;cout<<"引用的地址和相關(guān)變量地址相同:refA的地址="<<&refA<<endl;}6.5.2
引用的使用2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-47-
引用的值和相關(guān)變量值相同: refA=10引用的變化,則相關(guān)變量也變化: intA=5引用的地址和相關(guān)變量地址相同: intA的地址=0x0012FF7C引用的地址和相關(guān)變量地址相同: refA的地址=0x0012FF7C程序的結(jié)果6.6指針和引用作為函數(shù)的參數(shù)
2025/10/9-48-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-49-指針和函數(shù)在程序設(shè)計(jì)中,指針有很多應(yīng)用。其中之一就是用指針作為函數(shù)的參數(shù),從而形成了C++函數(shù)調(diào)用中的另一種調(diào)用方式:地址調(diào)用。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-50-6.6.1指針作為函數(shù)的參數(shù)用指針作為函數(shù)參數(shù),實(shí)現(xiàn)地址調(diào)用,必須滿足以下條件:函數(shù)的形式參數(shù)是指針變量;函數(shù)的實(shí)參數(shù)是內(nèi)存的地址,具體來說可以是數(shù)組名、變量的地址、用變量地址初始化的指針;形參指針類型和實(shí)參地址類型必須相同。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-51-6.6.1指針作為函數(shù)的參數(shù)滿足以上條件后,這樣的函數(shù)調(diào)用在使用上有以下的特點(diǎn):實(shí)參傳遞給形參的是內(nèi)存的地址,所以形參指針指向?qū)崊⒆兞?;形參指針通過間接引用,直接訪問實(shí)參變量,包括改變實(shí)參變量的值;函數(shù)調(diào)用后,可以保留對(duì)實(shí)參變量的操作結(jié)果,如果有多個(gè)實(shí)參,就可以有多個(gè)實(shí)參變量在函數(shù)調(diào)用中得到修改。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-52-
例6.8
編寫數(shù)據(jù)交換的函數(shù)。在main中調(diào)用這個(gè)函數(shù),交換main中定義的變量。
#include<iostream>usingnamespacestd;voidSwap(int*a,int*b);voidmain(){ intx(5),y(10);
cout<<"主函數(shù)變量的值:
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<<"函數(shù)中完成了交換:*a="<<*a<<"*b="<<*b<<endl;}
運(yùn)行結(jié)果:主函數(shù)變量的值:x=5y=10函數(shù)中完成了交換:*a=10*b=5返回后變量的值:
x=10y=5
變量的地址作為實(shí)參數(shù)指針變量作為形式參數(shù)2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-53-6.6.1指針作為函數(shù)的參數(shù)程序中用變量x和y的地址作實(shí)參,傳遞給指針a和b,如圖6.1(a)。通過間接引用*a和*b進(jìn)行交換,實(shí)際上就是x和y進(jìn)行交換,如圖6.1(b)。
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-54-6.6.2引用作為函數(shù)參數(shù)引用使用最多的場(chǎng)合是作為函數(shù)的形式參數(shù)。引用作為函數(shù)的形式參數(shù)具有以下的特點(diǎn):引用作為形式參數(shù)時(shí),實(shí)參數(shù)是相同類型的變量;引用作為形式參數(shù),參數(shù)傳遞屬于地址傳遞;引用作為形式參數(shù)時(shí),在函數(shù)中并不產(chǎn)生實(shí)參數(shù)的副本,形式參數(shù)的引用和實(shí)參數(shù)的變量實(shí)際上是同一個(gè)實(shí)體;函數(shù)對(duì)引用的操作,也是對(duì)實(shí)參變量的操作,函數(shù)調(diào)用可以改變實(shí)參數(shù)的值。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-55-
例6.9用引用作為形式參數(shù),通過函數(shù)調(diào)用,交換兩個(gè)實(shí)參數(shù)。
#include<iostream>usingnamespacestd;voidswap_1(int&x,int&y) //引用作為形式參數(shù){intj;j=x;x=y;y=j;}voidmain(){inta=12345,b=54321;cout<<"函數(shù)調(diào)用前:a="<<a<<"b="<<b<<endl;swap_1(a,b); //變量作為實(shí)參數(shù)
cout<<"函數(shù)調(diào)用后:a="<<a<<"b="<<b<<endl;}
函數(shù)調(diào)用前:a=12345b=54321
函數(shù)調(diào)用后:a=54321b=123452025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-56-6.6.2引用作為函數(shù)參數(shù)使用引用作為形式參數(shù)還需要注意:如果實(shí)參數(shù)需要保護(hù),可以使用“常引用”作為形式參數(shù);用引用作形參和用變量作形參是有區(qū)別的,但是,對(duì)于這兩種情況,實(shí)參數(shù)可能相同。例如,函數(shù)swap(inta,intb)和swap(int&a,int&b)看起來是兩個(gè)可以區(qū)分的重載函數(shù)。但是,都可以用整型變量x和y來調(diào)用:swap(x,y),因此,實(shí)際上是不可區(qū)分的,函數(shù)swap(inta,intb)和swap(int&a,int&b)不是可以區(qū)分的重載函數(shù)。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-57-6.6.3常指針和常引用常指針是指向常量的指針(PointertoConstantdata)的習(xí)慣說法。就是規(guī)定指針?biāo)赶虻膬?nèi)容不可以通過指針的間接引用來改變。常指針說明的格式是:
const<類型名>*<指針名>;
例如:constint*ptint;指針ptint的類型是(constint*),也就是指向一個(gè)恒定的整型數(shù)。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-58-
例6.10常指針示例。觀察以下程序的運(yùn)行。
#include<iostream>usingnamespacestd;voidmain(){intia=10,ib=20;constint*ptint; ptint=&ia; //用ia地址初始化cout<<*ptint<<endl;ptint=&ib; //改變?yōu)閕b的地址ib=ib+100; //ib本身仍然可以改變cout<<*ptint<<endl;//*ptint=100; //語句錯(cuò)誤:左值是常量}
運(yùn)行結(jié)果:10
120常指針聲明注釋去掉會(huì)出現(xiàn)編譯錯(cuò)誤2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-59-6.6.4指針的指針作為函數(shù)的參數(shù)如果一定要改變實(shí)參指針的值,可以用指針變量的地址作實(shí)參,形式參數(shù)就應(yīng)該是指針的指針。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-60-
例6.12
指針變量指向一個(gè)數(shù)組。用指針變量作為實(shí)參調(diào)用一個(gè)函數(shù)。在函數(shù)中指針指向數(shù)組的第二個(gè)元素。觀察函數(shù)返回后,實(shí)參指針值有無變化。
#include<iostream>usingnamespacestd;voidMove(int*a);voidmain(){ intx[5]={10,20,30,40,50},*px=x; cout<<"調(diào)用前的*px="<<*px<<endl;
Move(px); cout<<"調(diào)用后的px"; if(px==x)cout<<"沒有變化,*px還是"<<*px<<endl; elsecout<<"也向前移動(dòng),*px變?yōu)?<<*px<<endl;}voidMove(int*a){ a=a+1;cout<<"函數(shù)中完成了指針移動(dòng):*a="<<*a<<endl;}
運(yùn)行結(jié)果:調(diào)用前的*px=10
函數(shù)中完成了指針移動(dòng):*a=20調(diào)用后的px沒有變化*px還是10
指針作為實(shí)參數(shù)指針變量作為形式參數(shù)2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-61-
例6.13修改例6.12,使得實(shí)參指針返回后,指向新的地址。#include<iostream>usingnamespacestd;voidMove(int**a); voidmain(){ intx[5]={10,20,30,40,50},*px=x; cout<<"調(diào)用前的*px="<<*px<<endl; Move(&px); cout<<"調(diào)用后的px"; if(px==x)cout<<"沒有變化,*px還是"<<*px<<endl; elsecout<<"也向前移動(dòng),*px變?yōu)?<<*px<<endl;}voidMove(int**a){ *a=*a+1; cout<<"函數(shù)中完成了指針移動(dòng):**a="<<**a<<endl; }運(yùn)行結(jié)果:調(diào)用前的*px=10
函數(shù)中完成了指針移動(dòng):**a=20調(diào)用后的px也向前移動(dòng),*px變?yōu)?0
指針的地址作為實(shí)參數(shù)指針的指針作為形式參數(shù)6.7指針和引用作為函數(shù)的返回值
2025/10/9-62-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-63-6.7.1指針函數(shù)如果一個(gè)函數(shù)的返回值是指針,則這樣的函數(shù)稱為指針函數(shù)。如:
int*func01(intk);
函數(shù)func01返回一個(gè)指向整型數(shù)據(jù)的指針。返回指針,實(shí)際就是返回一個(gè)內(nèi)存的地址。要注意:不能返回函數(shù)中局部變量的地址。這樣的地址處于內(nèi)存的堆棧區(qū),是所有函數(shù)公用的區(qū)域。其中的數(shù)據(jù)是不穩(wěn)定的,可能因?yàn)槠渌瘮?shù)的執(zhí)行而發(fā)生改變。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-64-
例6-15一個(gè)指針函數(shù)完成一個(gè)數(shù)組的倒序。源數(shù)組由函數(shù)參數(shù)傳遞,倒序后的數(shù)組地址由指針函數(shù)返回。#include<iostream>usingnamespacestd;int*reverse(intconst*list,constintsize) //指針函數(shù){intresult[6]; //函數(shù)中定義的局部數(shù)組
for(inti=0,j=size-1;i<size;i++,j--){result[j]=list[i];}returnresult; //返回局部數(shù)組的地址}2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-65-
voidprintArray(intconst*list,constintsize){for(inti=0;i<size;i++)cout<<list[i]<<"";}voidmain(){intlist[]={1,2,3,4,5,6};int*pList=reverse(list,6);//獲得倒序后數(shù)組的地址
printArray(pList,6); //顯示倒序后的數(shù)組}程序運(yùn)行結(jié)果:-858993460-858993460-858993460-858993460-8589934605結(jié)果完全不對(duì)。原因就在于指針函數(shù)返回的是函數(shù)局部數(shù)組的地址。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-66-
例6-16對(duì)例6-15的修改。只要修改指針函數(shù)reverse。可以在函數(shù)這申請(qǐng)一個(gè)動(dòng)態(tài)數(shù)組的地址,最后返回這個(gè)地址就可以。注意不要忘了用delete來釋放這個(gè)地址。#include<iostream>usingnamespacestd;int*reverse(intconst*list,constintsize) //指針函數(shù){int*result=newint[size]; //函數(shù)中定義的動(dòng)態(tài)數(shù)組
for(inti=0,j=size-1;i<size;i++,j--){result[j]=list[i];}returnresult; //返回動(dòng)態(tài)數(shù)組的地址}2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-67-
voidprintArray(intconst*list,constintsize){for(inti=0;i<size;i++)cout<<list[i]<<"";}voidmain(){intlist[]={1,2,3,4,5,6};int*pList=reverse(list,6); //獲得倒序后數(shù)組的地址
printArray(pList,6); //顯示倒序后的數(shù)組
deletepList;}程序運(yùn)行結(jié)果:6543212025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-68-6.7.2用引用作為函數(shù)的返回值返回引用有以下需要注意的地方:返回引用需要在函數(shù)的返回值類型中加以說明,形式為:
<類型名>&函數(shù)名(形式參數(shù)表)返回引用的返回語句就是:return變量名;返回引用實(shí)際是返回地址。在使用上,或者直接使用這個(gè)地址;或者使用這個(gè)地址單元的數(shù)據(jù)。返回的引用可以作為左值繼續(xù)操作,而返回的變量值是不可以繼續(xù)運(yùn)算的。這是返回引用和返回變量值在使用上的主要區(qū)別。2025/10/9
//例6-17引用作為函數(shù)的返回值#include<iostream>#include<iomanip>usingnamespacestd;structperson{charname[15];intcontribution;doublebonus;}; //定義結(jié)構(gòu)體personp1={"LiLi",500,0},p2={"ZhaoZhao",600,0}; //兩名職工是全局變量person&compare() //返回引用的函數(shù){if(p1.contribution>p2.contribution) returnp1;elsereturnp2;}2025/10/9
例6.17引用作為函數(shù)返回值。
voidmain(){compare().bonus=1000; //返回值作為左值直接操作
cout<<setw(10)<<<<""<<p1.contribution<<""<<p1.bonus<<endl;;cout<<setw(10)<<<<""<<p2.contribution<<""<<p2.bonus<<endl;;}程序運(yùn)行結(jié)果:
LiLi5000ZhaoZhao60010006.8指針和字符串
2025/10/9-71-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-72-6.8.1字符串處理的兩種方式C++字符串常量是用雙引號(hào)括起的字符序列,并以字符‘\0’作為結(jié)束標(biāo)志。如 "Thisisastring"。字符串常量存放在內(nèi)存的某個(gè)區(qū)域,有自己固定的首地址。如果將字符串常量的首地址看成是指針,這種指針既是常指針,也是指針常量。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-73-6.8.1字符串處理的兩種方式C++處理字符串有兩種方式:數(shù)組方式和指針方式。數(shù)組方式是將字符串存入字符數(shù)組后,再進(jìn)行處理。一般可以在聲明數(shù)組的時(shí)候用字符串來初始化:charstring_array[]="What’saniceday!";指針方式是用字符串常量來初始化一個(gè)字符指針:char*string_pt="What’saniceday!";2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-74-6.8.1字符串處理的兩種方式常量不能放在等式左邊運(yùn)行時(shí)會(huì)出錯(cuò)2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-75-6.8.2字符串操作函數(shù)
調(diào)用這些函數(shù)時(shí),原則上可以使用字符數(shù)組名、已經(jīng)初始化的字符指針作為實(shí)參數(shù)。字符串常量還可以作為源字符串的實(shí)參數(shù)。目的串必須是可寫的。2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-76-
例6.18
strcpy和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); //復(fù)制array1的n-1個(gè)字符到array3array3[14]='\0'; //添加'\0'到array3cout<<"Thestringinarray3is:"<<array3<<endl;}
不包括提示的運(yùn)行結(jié)果HappyBirthdaytoYouHappyBirthdaytoYouHappyBirthday
復(fù)制array1到array2,沒有問題復(fù)制array1到array3,空間不夠,有運(yùn)行錯(cuò)誤按實(shí)際數(shù)組大小,復(fù)制array1到array3,沒有問題6.9通過指針訪問數(shù)組
2025/10/9-77-北京郵電大學(xué)信息與通信工程學(xué)院2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-78-通過指針訪問數(shù)組指針和數(shù)組有天然的聯(lián)系。因?yàn)閿?shù)組名本身就是地址,也就是某種類型的指針。將指針和數(shù)組名聯(lián)系起來,訪問數(shù)組就多了一種方法。雖然一維數(shù)組名和二維數(shù)組名都是地址,都可以看作是某種指針,但是指針的類型是不同的。因此,通過指針訪問一維數(shù)組和二維數(shù)組的方法是不同的。
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-79-6.9.1通過指針訪問一維數(shù)組要通過指針訪問一維數(shù)組,必須首先聲明一個(gè)和數(shù)組類型相同的指針,并且用數(shù)組名來對(duì)指針初始化,如:
intA[10],*pa=A;然后,就可以用多種方式訪問數(shù)組元素:數(shù)組名和下標(biāo),如A[0]、A[4];指針和下標(biāo),如pa[0]、pa[4];指針加偏移量的間接引用,如*(pa+4);數(shù)組名加偏移量的間接引用,如*(A+4);指針自加后的間接引用,如*pa++。
2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-80-
例6.19求數(shù)組內(nèi)所存放的字符串的長(zhǎng)度。#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;}
運(yùn)行結(jié)果都相同方式1:數(shù)組名和下標(biāo)方式2:指針和下標(biāo)方式3:數(shù)組名加偏移量的間接引用方式4:指針加偏移量的間接引用方式5:指針自加的間接引用2025/10/9北京郵電大學(xué)信息與通信工程學(xué)院-81-
例6.20求整型數(shù)組的平均值,顯示數(shù)組元素和平均值。#include<iostream>usingnamespacestd;voidmain(){intintArray[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)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 企業(yè)盤點(diǎn)制度
- 嚴(yán)格落實(shí)請(qǐng)休假制度
- 企業(yè)環(huán)保法規(guī)知識(shí)培訓(xùn)課件
- 2025-2030中國電警棍行業(yè)供給變化趨勢(shì)與發(fā)展現(xiàn)狀調(diào)研研究報(bào)告
- 2025-2030中國非那唑酮(安替比林)行業(yè)市場(chǎng)發(fā)展趨勢(shì)與前景展望戰(zhàn)略研究報(bào)告
- 2025-2030中國腹膜透析(PD) 市場(chǎng)運(yùn)營(yíng)風(fēng)險(xiǎn)與未來建設(shè)現(xiàn)狀研究研究報(bào)告
- 2025至2030中國工業(yè)型材市場(chǎng)需求變化與產(chǎn)能布局研究報(bào)告
- 2025-2030中國牛蛙飼料行業(yè)現(xiàn)狀調(diào)查與營(yíng)銷策略分析研究報(bào)告
- 2025-2030中文教育機(jī)構(gòu)運(yùn)營(yíng)效率提升措施研究及海外招生渠道拓展計(jì)劃制定效果分析報(bào)告
- 2025至2030中國光伏發(fā)電行業(yè)政策支持力度與平價(jià)上網(wǎng)時(shí)代盈利模式研究報(bào)告
- DB63-T 2256.3-2025 水利信息化工程施工質(zhì)量評(píng)定規(guī)范 第3部分 水情監(jiān)測(cè)系統(tǒng)
- 患者身份識(shí)別錯(cuò)誤應(yīng)急預(yù)案與處理流程
- 25年軍考數(shù)學(xué)試卷及答案
- 化工儲(chǔ)存設(shè)備知識(shí)培訓(xùn)課件
- 血透室水處理維護(hù)課件
- 服裝企業(yè)庫存優(yōu)化管理方案
- 低壓作業(yè)實(shí)操科目三安全隱患圖片題庫
- DB1331-T 114-2025 雄安新區(qū)近零碳變電站技術(shù)標(biāo)準(zhǔn)
- c1學(xué)法減分考試題庫及答案
- 恩施排污管理辦法
- 柔性引才協(xié)議書
評(píng)論
0/150
提交評(píng)論