![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iYjJDO4Q2MzQDOwUDM3cTM3cjMwYWNiJmMzQjM5QmY58CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
本文講關于什麼是指針以及它們如何操作的全方位概述。
最近,我被介紹了C ++中的指針。我花了一些時間才了解正在發生的事情。這是我有使用指針的任何經驗的第一門語言。我的許多同齡人仍然對指針有疑問,我想将其用作該資訊的簡潔資源。我希望這不僅對他們有幫助,對其他可能也有疑問的人也有幫助。
變量,記憶體和位址
首先,要了解什麼是指針,我們必須對變量和記憶體有所了解。當建立諸如char,short和float的變量時,将為該變量配置設定足夠的空間來容納該變量資料類型的值。例如,char的一個位元組,shorts的兩個位元組和int的4位元組是常見的。存儲器的每個位元組都有一個唯一位址,變量的指定位址是資訊的第一個位元組存儲的位置。
要擷取C ++中變量的位址,我們使用
&(&)運算符。假設我們有
int myInt = 4。為了通路myInt的位址,我們将&運算符放在變量名..
&myInt的前面。它不會為您提供在記憶體中找到的4,而是為您提供該變量的存儲位置。您将獲得一個位址,例如0x8f05。
價值傳遞和參考傳遞
我認為,準确地了解使用特定語言傳遞的變量或對象時發生的情況非常重要。它們因語言而異。在C ++中,變量和對象按值傳遞。一種簡單的想法是,當您将變量傳遞給函數時,實際上是在傳遞該變量的副本。變量的副本對您傳遞給函數的參數無效。現在,它們是兩個完全不同的變量。該副本僅在功能本地。該副本具有關聯的存儲持續時間,并且在函數運作其過程之後将被釋放。
通過引用傳遞某些内容時,它不會被複制,但是實際上您傳遞的是對原始資料的引用。是以,該資料基本上具有兩個名稱,但都“指向”同一資料。在下面的插圖中,myInt是儲存int 4的原始變量。将myInt傳遞給函數時,将通過參數名稱引用該資料。在這種情況下,我們使用myReference。當您使用myReference時,它将直接影響myInt中的資料,并且它們現在都可以通路該資料。您隻能在函數内部将該資料稱為myReference。
那麼,如果變量按值傳遞,為什麼要解釋按引用傳遞?好吧,一個人很好地了解這兩者是如何工作的。對這些概念的清晰了解越快,您的生活就會越輕松。其次,盡管變量是在C ++中按值傳遞的,但是您仍然可以通過引用來顯式傳遞變量。記得之前我曾解釋過使用
&變量名稱傳回位址之前的運算符?您可以在函數的參數中使用相同的運算符來接受參數的位址。這樣做将通過引用傳遞該值,并且您對該資料所做的任何操作也會影響原始資料中的資料,因為它們都“指向”同一資料。盡管指針和引用變量看起來很相似,但還是存在一些差異,例如指針算法。
指針到底是什麼?
好吧,指針實際上是一個指針變量。如果您記得它是一個變量,則可能會使事情更容易了解。指針旨在儲存記憶體位址。名稱指針非常清楚。它“指向”存儲在計算機記憶體中的資料。這使您可以間接處理它們指向的資料。
指針的定義與任何其他定義非常相似:
int * ptr。ptr前面的
*(星号)表示ptr是指針變量,而int表示ptr将指向整數。定義指針變量而不初始化它絕不是一個好主意。如果你有,你可以将其指定
nullptr像
INT * PTR = nullptr。這将把指針配置設定給位址0。現在,使用&運算符傳回以擷取位址,将指針配置設定給變量,您可以使用
int * ptr =&myInt。這會将myInt的位址配置設定給ptr指針變量。myInt和ptr都指向儲存myInt中資料的相同位址。是以,在将ptr配置設定給myInt之後,如果要使用
ptr = 5,則會将5配置設定給myInt。要通路指針所引用的資料,我們在指針之前放置一個
*。這稱為間接運算符。通過使用
* ptr,它将取消引用指針并傳回
5而不是位址。
考慮一個數組。當将數組傳遞給函數時,您實際上不是在傳遞數組,而是在傳遞數組的起始位址。傳入參數名稱為myReferemce的函數中的名為myArr的數組變量将指向myArr數組。實際上,由于C的限制,您不能在C ++中按值傳遞數組(C ++派生自C)。看下面的例子,當您為數組建立帶有形式參數的函數時,它接受傳遞給它的位址的起始位址。
指針算術
不帶方括号或下标的數組名稱表示數組的起始位址。取消引用myArray時,它将傳回存儲在該數組的起始位址
* myArr == myArr [0]上的内容。數組以連續順序一起存儲在記憶體中。要使用間接運算符通路數組的内容,我們需要加或減以獲得其他元素的位址。例如,
*(myArr + 1)将為您擷取存儲在
myArr [1]中的資料
。幕後實際發生的是
myArr + 1 * 4。當您從解引用的數組中增加或減少一個數字時,它将在該數組中增加或減少一個存儲在其中的大小。是以,由于我們的數組是一個int數組,是以我們可以假定為每個元素配置設定的大小為4。每個增量将從起始點移動4個位元組到存儲該int的下一個位址。幾件事要注意:
- myArr [index] == *(myArr + index)
- *(myArr + 1)!= * myArr + 1…如果沒有括号,将取消對myArr的引用,并将1添加到存儲的值中。
- 請記住,在C ++數組中并沒有專門處理通路無效索引的問題。這被歸類為未定義的行為,實際上任何事情都可能發生,是以請確定跟蹤您在做什麼。
指針作為函數參數
建立使用指針參數的函數時,必須與上面類似地編寫它。您必須指定此函數的參數是一個指向int的指針。然後,您可以使用&運算符傳遞數字的位址。在函數内部,值被解引用并乘以2。這也間接改變了資料的數量,因為它們都指向記憶體中的同一資料。
常數
這看似令人困惑,但我将盡我所能将其分解。有3種關系:
- 指向常量的指針
在函數中,
const int定義值指向的内容。常量适用于值所指向的東西,而不是值本身(注意定義在星号之前)。另外,星号表示該值是一個指針。像所有常量一樣,編譯器不允許我們編寫更改事物值指向的代碼。
雖然,指針指向的資料不能更改,指針本身可以更改。而且,常量位址隻能傳遞給指向常量的指針,指向常量的指針可以接收非常量項的位址。
- 常數指針
前面我們讨論了指向常量的指針,而常量指針描述了指針本身。用位址初始化常量指針時,它不能指向其他任何對象。請注意,這次const的定義在星号之後。這将幫助您知道const單詞是在定義指針,而不是指針指向的對象。盡管不能更改常量指針,但由于數字不是常量,是以可以更改其指向的資料。
- 常數指向常數
如果您了解以前的關系,那麼應該很熟悉。這隻是兩者的結合。
Const int(在星号之前)描述了ptr指向的内容。
const ptr(在星号之後)描述了指針本身。請記住,指向常量的指針可以接受非常量的位址。即使number不是一個常數,我們也聲明了它指向一個常數,是以該指針無權更改其指向的值。另外,我們已将其聲明為常量指針,是以無法更改該指針指向的位址。
動态記憶體配置設定
是以,在編寫代碼時,您會熟悉建立執行期間所需的變量。假設您現在在編寫代碼的時候不知道需要多少變量。你是做什麼?通常,以數組為例,必須為數組的大小提供一個常數,但要使用動态記憶體配置設定,就必須允許程式建立自己的變量。這隻能通過使用指針來實作。
簡而言之,在程式運作時,它将要求計算機配置設定特定大小的未使用記憶體塊,其大小足以容納該資料。計算機将尋找該未使用的空間并傳回該位置的起始位址。通路配置設定的記憶體的唯一方法是通過位址。那就是需要指針的地方。
您已經熟悉如何建立指針:
int * ptr = nullptr(請記住始終初始化指針)。要為變量配置設定空間,您将使用“
new”關鍵字,後跟資料類型。例如,
int * ptr = new int,或者如果已經建立了指針,則可以使用
ptr = new int。現在,新配置設定的位址已儲存在指針中,并且可以通過用*取消引用指針來輕松通路。
下面是擷取要輸入到數組中的ID号數量的使用者輸入的示例,然後,使用使用者的輸入變量建立一個指針和一個新數組以指定數組的确切大小。
沒有指針和動态記憶體配置設定,這将是不可能的。通常,在正常情況下建立的數組必須使用常量聲明數組大小。在這裡,我們能夠即時進行操作,需要注意一些事項。如果沒有足夠的可用記憶體來容納該請求,則C ++将引發異常并終止程式。
使用後删除或重新配置設定記憶體很重要。這将有助于阻止記憶體洩漏的發生。C ++沒有垃圾回收。垃圾收集是一種機制,可以回收不再使用的堆上的資料。由于C ++不提供此實用程式,是以取決于您。使用
delete ptr(單變量) 或
delete [] ptr(數組)将釋放該記憶體并釋放該空間。C ++也有
智能指針。牛逼嘿是工作方式與指針,但是當它不再使用可以自動删除配置設定的記憶體對象。
總結思想
我希望它能夠提供一些有用的資訊并消除任何混亂。指針是C ++程式設計的重要組成部分,對此牢牢掌握将是有益的。我不是該主題的專家,但這隻是我對該主題的功能了解。将這些資訊放入我自己的語言和思想中,使我能夠反思自己的實際了解。這對我和其他需要它的人來說都是學習工具。如果您有任何疑問,或者也許我需要進行一些更正,請随時給我評論或發送消息。