溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++中指針實(shí)例分析

發(fā)布時(shí)間:2022-03-28 15:33:31 來源:億速云 閱讀:144 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“C++中指針實(shí)例分析”的相關(guān)知識(shí),小編通過實(shí)際案例向大家展示操作過程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“C++中指針實(shí)例分析”文章能幫助大家解決問題。

計(jì)算機(jī)的內(nèi)存模型

CPU是計(jì)算機(jī)的核心部件,要想讓一個(gè)CPU工作,就必須向它提供指令和數(shù)據(jù),指令和數(shù)據(jù)在存儲(chǔ)器中存放,也就是我們平時(shí)說的內(nèi)存。

內(nèi)存分為:物理內(nèi)存和虛擬內(nèi)存,物理內(nèi)存對(duì)應(yīng)著計(jì)算機(jī)中的內(nèi)存條,虛擬內(nèi)存是操作系統(tǒng)內(nèi)存管理系統(tǒng)假想出來的,由于這些不是我們本文的重點(diǎn),我們就不做區(qū)分。

在不考慮cpu緩存的情況下,計(jì)算機(jī)運(yùn)行程序本質(zhì)上是對(duì)內(nèi)存中的數(shù)據(jù)的操作,存儲(chǔ)器被劃分為多個(gè)存儲(chǔ)單元,存儲(chǔ)單元從零開始順序編號(hào),CPU要從內(nèi)存中讀取數(shù)據(jù),首先要指定存儲(chǔ)單元的地址。

CPU從內(nèi)存中讀取數(shù)據(jù)的過程如圖所示:

C++中指針實(shí)例分析

計(jì)算機(jī)為了方便管理內(nèi)存,將內(nèi)存的每個(gè)單元用一個(gè)數(shù)字編號(hào)

指針與指針常量

指針的本意就是內(nèi)存地址,我們可以通俗的理解成內(nèi)存編號(hào),既然計(jì)算機(jī)通過編號(hào)來操作內(nèi)存單元,這就造成了指針的高效率

指針變量:

  • 通俗理解為存儲(chǔ)指針的變量,也就是存儲(chǔ)內(nèi)存地址(內(nèi)存編號(hào))的變量

  • 指針變量和int,float,char等類型一樣同屬變量類型,指針變量類型占四個(gè)字節(jié)(32位機(jī)器下),存儲(chǔ)的是32位的內(nèi)存地址
    星號(hào):

  • 在CC++中(*)被定義為取內(nèi)容符號(hào)

  • 雖然所有指針變量占的內(nèi)存大小和存儲(chǔ)的內(nèi)存地址大小都是一樣的,但是由于存儲(chǔ)的只是數(shù)據(jù)的內(nèi)存首地址,所以指針變量存儲(chǔ)的內(nèi)存地址所指向的數(shù)據(jù)類型決定著如何解析這個(gè)首地址

  • 比如int型指針變量,我們需要從該指針變量存儲(chǔ)的首地址開始向后一直搜索4個(gè)字節(jié)的內(nèi)存空間

  • 所以當(dāng)我們使用*p,必須知道p是一個(gè)什么類型的指針

指針變量和指針常量

指針變量首先是一個(gè)變量,由于指針變量存儲(chǔ)了某個(gè)變量的內(nèi)存首地址,我們通常認(rèn)為"指針變量指向了該變量",同時(shí)指針變量時(shí)一個(gè)變量,它的值是可以變動(dòng)的。

相反,指針常量可通俗地理解為存儲(chǔ)固定的內(nèi)存單元地址編號(hào)的量,它一旦存儲(chǔ)了某個(gè)內(nèi)存地址以后,不可再改存儲(chǔ)其他的內(nèi)存地址了

舉個(gè)例子:

void f(const int *x,int *y)
{
	*x=2;//錯(cuò)誤,由于x前面有個(gè)const修飾,所以不可以修改x所指向的內(nèi)存單元的內(nèi)容
	//正確寫法
	*y=3;
}

指針變量和數(shù)組

先看一個(gè)例子:

	int a[5]={1,2,3,4,5};
	int *ptr=(int*)(&a+1);
	cout<<*(a+1)<<endl;
	cout<<*(ptr-1)<<endl;

輸出結(jié)果為2和5,首先我們看一下&a+1的含義:

  • 我們知道CC++中規(guī)定數(shù)組名表示這個(gè)數(shù)組的首地址,而這里出現(xiàn)了&a這樣的符號(hào),本來a就是指針常量,再次取地址難道不是非法操作?

  • 這時(shí)我們可以將這個(gè)&a看成是指向數(shù)組的指針,也稱為行指針,&a的類型是int (*p)[5],一個(gè)步長(zhǎng)即5個(gè)元素的長(zhǎng)度,&a + 1代表往后移動(dòng)一個(gè)步長(zhǎng)

分析:

  • a表示的是第一個(gè)元素的首地址,那么a+1指向的就是下一個(gè)元素的內(nèi)存首地址,所以*(a+1)=2

  • 而&a則表示整個(gè)數(shù)據(jù)的首地址,那么&a+1移動(dòng)的內(nèi)存數(shù)目就是整個(gè)數(shù)組所占字節(jié)數(shù),假如原先數(shù)組中第一個(gè)元素的首地址是0,那么&a+1表示的就是20,而這個(gè)地址已經(jīng)不屬于數(shù)組了,接著通過(int*)(&a+1)將數(shù)組指針轉(zhuǎn)換成整型指針,這樣原先&a+1表示的數(shù)據(jù)范圍20-39就縮小為20-23,正好是一個(gè)int型的大小,而ptr-1就是16了,表示的數(shù)據(jù)內(nèi)存范圍是16-19,這樣*(ptr-1)正好是最后一個(gè)元素5了

上面的例子,只是通過簡(jiǎn)單的數(shù)據(jù)類型來說明內(nèi)存分布,但是實(shí)際上一些復(fù)雜的數(shù)據(jù)類型,尤其是一些自定義的類或者結(jié)構(gòu)體類型,內(nèi)存分布還要充分考慮到字節(jié)對(duì)齊。

函數(shù)指針

函數(shù)指針是指向函數(shù)的指針變量,CC++程序在編譯時(shí),每個(gè)函數(shù)都有一個(gè)入口地址,該入口地址就是函數(shù)指針?biāo)赶虻牡刂?,有了指向函?shù)的指針變量后,可用該指針變量調(diào)用函數(shù),同時(shí)也可以做函數(shù)的參數(shù)

我們先看函數(shù)指針調(diào)用函數(shù),如下:

int f(int x, int y) {
	return x + y;
}
//申明一個(gè)函數(shù)指針
typedef int (*pf)(int, int);
int main()
{
	int a = 1;
	int b = 2;
	//將函數(shù)f地址賦給函數(shù)指針pf
	pf = f;
	//利用函數(shù)指針調(diào)用函數(shù)
	int c = (*pf)(a, b);
	cout << c << endl;
}

需要注意的是,定義的函數(shù)指針類型時(shí)的函數(shù)簽名(包括函數(shù)返回值和函數(shù)參數(shù)列表的類型,個(gè)數(shù),順序)要將賦值給該類型變量的函數(shù)簽名保持一致,不然可能會(huì)發(fā)生很多無法預(yù)料的情況,還有CC++規(guī)定函數(shù)名就表示函數(shù)入口地址,所以,函數(shù)名賦值時(shí)函數(shù)名前面加不加取地址符&都一樣,但是在C++中取類的方法函數(shù)的地址時(shí),這個(gè)&符號(hào)不能省略。

函數(shù)指針還有另外一個(gè)用處,就是作為一個(gè)函數(shù)的參數(shù),在Windows編程中作為回調(diào)函數(shù)很常見:

typedef int (*PF)(int, int);
int f1(int x, int y)
{
	return x + y;
}
int f2(PF pf, int t)
{
	return (*pf)(3, t);
}
int main()
{
	//將函數(shù)f1作為參數(shù)傳遞給函數(shù)f2
	int c = f2(f1, 4);
	cout << c << endl;
	return 0;
}

C++中的引用

所謂引用,使用另外一個(gè)變量名來代表某一塊內(nèi)存,這就相當(dāng)于同一個(gè)人有不同的名字,但是不管哪個(gè)名字,指的都是同一個(gè)人。

int a=1;
//通過&符號(hào),將b定義為a的引用
int &b=a;
//b和a完全一樣,等價(jià)于int c=a
int c=b;

注意,C++規(guī)定,定義一個(gè)引用的時(shí)候,必須馬上初始化

傳值還是傳引用

如果變量類型是基元數(shù)據(jù)類型,比如int,float,bool,char等小數(shù)據(jù)類型被稱為基元數(shù)據(jù)類型,那么賦值時(shí)傳的是值,這時(shí)候b的值是a的拷貝,那么更改b不會(huì)影響到a,但是,如果變量數(shù)據(jù)類型是復(fù)雜數(shù)據(jù)類型,比如數(shù)組,類對(duì)象,那么賦值時(shí)傳的就是引用,這個(gè)時(shí)候,a和b指向的都是同一個(gè)內(nèi)存區(qū)域,那么無論更改a或者b都會(huì)相互影響。

最后,在利用C++中拷貝構(gòu)造函數(shù)復(fù)制對(duì)象時(shí)需要注意,基元數(shù)據(jù)類型可以直接復(fù)制,但是對(duì)于引用類型數(shù)據(jù),我們需要實(shí)現(xiàn)引用類型的真正復(fù)制

C++中的new關(guān)鍵詞

在c++中通過new關(guān)鍵詞定義一個(gè)對(duì)象,不能直接得到對(duì)象的實(shí)例,我們需要用一個(gè)指針去接收這個(gè)new出來的對(duì)象,我們引用這個(gè)對(duì)象必須使用指針引用運(yùn)算符->

#include <iostream>
using namespace std;
class Person
{
public:
	Person()
	{

	}
	Person(int a, int b)
	{
		this->m_a = a;
		this->m_b = b;
	}
	int m_a;
	int m_b;
};
int main()
{
	//在C++中可以用以下形式來實(shí)例化一個(gè)對(duì)象,per1和per2為實(shí)例化的person類對(duì)象
	Person per1;
	int i = 1;
	int j = 2;
	Person per2(i, j);
}

在C++中,this關(guān)鍵詞是一個(gè)指針,而不像在java中是一個(gè)類實(shí)例,在C++中*this才等價(jià)于java

class Person
{
public:
	Person(int number)
	{
		//C++中需要使用指針引用符號(hào)
		this->m_number = number;
	}
	//返回對(duì)象本身,,需要使用引用,因?yàn)榉祷刂禃r(shí)會(huì)創(chuàng)建一個(gè)新的對(duì)象,使用引用的方式不會(huì)創(chuàng)建新的對(duì)象
	Person& getSelf()
	{
		return *this;
	}
	int m_number;
};

關(guān)于“C++中指針實(shí)例分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI