最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
(四)指針-創(chuàng)新互聯(lián)
指針(四)指針
通過指針程序員可以直接對內(nèi)存進行操作,這樣的優(yōu)點是使程序緊湊、簡潔、高效;
計算機保存地址的工具就是指針。所以說:
指針:就是用來保存內(nèi)存地址的變量。

注:指針地址、指針保存的地址和該地址的值 這三個概念一定不要混淆哦

什么是地址?

成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、成都網(wǎng)站建設(shè)、微信開發(fā)、微信小程序、集團成都企業(yè)網(wǎng)站定制等服務(wù)項目。核心團隊均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗,服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:小攪拌車等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗,同時也獲得了客戶的一致稱譽!
假如我們要去動物園,那么我們就得先知道動物園的地址,然后我們就可通過該地址找到動物園
同理,計算機要找到變量i,必須先找到i的地址,也就是i在內(nèi)存中的編號,然后通過該編號,計算機訪問到了i并且對它進行操作。
那么計算機將如何獲得i的地址呢?

//通過一個例子來了解計算機獲取地址
例:

#include
using namespace std;
int main(){
  int i=1;
  //&的作用是獲取變量i在內(nèi)存中的地址
  cout<<&i<}

使用指針的原因

因為在操作大型數(shù)據(jù)和類時,由于指針可以通過內(nèi)存地址直接訪問數(shù)據(jù),從而避免在程序中復制大量的代碼,因此指針的效率高。
一般來說,指針會有三大用途:
  1:處理堆中存放的大型數(shù)據(jù).
  2:快速訪問類的成員數(shù)據(jù)和函數(shù).
  3:以別名的方式向函數(shù)傳遞參數(shù).

//下面的可看可不看 沒多大作用
內(nèi)存的棧和堆
  一般來說,程序就是與數(shù)據(jù)打交道,在執(zhí)行某一功能的時候,將該功能所需要的數(shù)據(jù)加載到內(nèi)存中,然后在執(zhí)行完畢的時候釋放掉內(nèi)存。
  數(shù)據(jù)在內(nèi)存中的存放共分為以下幾個形式:
    1.棧區(qū)(stack)--由編譯器自動分配并且釋放,該區(qū)域一般存放函數(shù)的參數(shù)值、局部變量的值等。
    2.堆區(qū)(heap)--一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時可能由操作系統(tǒng)回收。
    3.寄存器區(qū)--用來保存棧頂指針和指令指針。
    4.全局區(qū)(靜態(tài)區(qū) static)--全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局
     變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域.程序結(jié)束后由系統(tǒng)釋放。
    5.文字常量區(qū)--常量字符串是放在這里的,程序結(jié)束后由系統(tǒng)釋放。
    6.程序代碼區(qū)--存放函數(shù)體的二進制代碼。
  函數(shù)參數(shù)和局部變量存放在棧中,當函數(shù)運行結(jié)束并且返回時,所有的局部變量和參數(shù)就都被系統(tǒng)自動清楚掉了,為的是釋放掉它們所占用
  的內(nèi)存空間,全局變量可以解決這個問題,但是全局變量永遠不會被釋放,而且由于全局變量被所有的類成員和函數(shù)所公用,所以它的值很
  容易被修改.使用堆可以一舉解決這兩個問題。
    堆和棧的區(qū)別:
      1.從內(nèi)存的申請方式上的不同
        棧:由系統(tǒng)自動分配,例如我們在函數(shù)中聲明一個局部變量 int a;那么系統(tǒng)就會自動在棧中為變量a開辟空間。
        堆:需要程序員自己申請,因此也需要指明變量的大小
      2.系統(tǒng)相應(yīng)的不同
        棧:只要棧的剩余空間大于所申請空間,系統(tǒng)將為程序提供內(nèi)存,否則將提示overflow,也就是棧溢出。
        堆:系統(tǒng)收到程序申請空間的要求后,會遍歷一個操作系統(tǒng)用于記錄內(nèi)存空閑地址的鏈表,當找到一個空間大于所申請空間的
          堆結(jié)點后,就會將該結(jié)點從記錄內(nèi)存空閑地址的鏈表中刪除。并將該結(jié)點的內(nèi)存分配給程序,然后在這塊內(nèi)存區(qū)域的首
          地址處記錄分配的大小,這樣我們在使用delete來釋放內(nèi)存的時候,delete才能正確地識別并刪除該內(nèi)存區(qū)域的所有
          變量.另外,我們申請的內(nèi)存空間在堆結(jié)點上的內(nèi)存空間不一定相等,這時系統(tǒng)就會自動將堆結(jié)點上多出來的那一部分內(nèi)存
          空間回收到空閑鏈表中
      3.空間大小的不同
        棧:在WINDOW下,棧是一塊連續(xù)的內(nèi)存的區(qū)域,它的大小是2M,也有的說是1M,總之該數(shù)值是一個編譯時就確定的常數(shù)。是
          由系統(tǒng)預先根據(jù)棧頂?shù)牡刂泛蜅5拇笕萘慷x好的。假如你的數(shù)據(jù)申請的內(nèi)存空間超過棧的空間,那么就會提示
          overflow.因此,別指望棧存儲比較大的數(shù)據(jù)
        堆:堆是不連續(xù)的內(nèi)存區(qū)域。各塊區(qū)域由鏈表將它們串聯(lián)起來,關(guān)于鏈表的知識將在后面了解。這里只需要知道鏈表將各個
          不連續(xù)的內(nèi)存區(qū)域連接起來,這些串聯(lián)起來的內(nèi)存空間叫做堆,它的上線是由系統(tǒng)中有效的虛擬內(nèi)存來定的。因此獲得
          的空間比較大,而且獲取空間的方式也比較靈活。
      4.執(zhí)行效率的不同
        棧:棧是由系統(tǒng)自動分配,因此速度較快.但是程序員不能對其進行操作。
        堆:堆是由程序員分配的內(nèi)存,一般速度比較慢,而且容易產(chǎn)生內(nèi)存碎片,不過用起來很方便。
      5.執(zhí)行函數(shù)時的不同
        棧:在函數(shù)調(diào)用時,第一個進棧的是被調(diào)用函數(shù)下一行的內(nèi)存地址。其次是函數(shù)的參數(shù),假如參數(shù)多于一個,那么次序是從右
          往左。最后才是函數(shù)的局部變量。
          由于棧的先進后出原則,函數(shù)結(jié)束時正好與其想反,首先是局部變量先出棧,然后是參數(shù),次序是從左到右,這是所有的變
          量都已出棧,指針自然地指到第一個進棧的那行內(nèi)存地址,也就是被調(diào)用函數(shù)的下一行內(nèi)存地址。程序根據(jù)該地址跳轉(zhuǎn)到
          被調(diào)用函數(shù)的下一行自動執(zhí)行。
        堆:堆是一大堆不連續(xù)的內(nèi)存區(qū)域,在系統(tǒng)中由鏈表將它們串接起來,因此在使用的時候必須由程序員來安排。它的機制是
         很復雜的,有時候為了分配一塊合適的內(nèi)存,程序員需要按照一定的算法在堆內(nèi)存中搜索可用的足夠大小的空間,如果
          沒有滿足條件的空間,那么就要向系統(tǒng)發(fā)出申請增加一部分內(nèi)存空間,這樣就才有機會分到足夠大小的內(nèi)存,然后將計
          算機后的數(shù)值返回。顯然,堆的運行效率比棧要低得多,而且也容易產(chǎn)生碎片,但是好處是堆可以存儲相當大的數(shù)據(jù),
          并且一些細節(jié)也可以由程序員來安排。
    終結(jié):
      棧的內(nèi)存小,但是效率高,不過存儲的數(shù)據(jù)只在函數(shù)內(nèi)有效,超出函數(shù)就消失了。堆的可存儲空間可以非常大,但是容易產(chǎn)生
      內(nèi)存碎片,效率也較低,好處是靈活性比較強。比如說我們需要創(chuàng)建一個對象,能夠被多個函數(shù)所訪問,但是又不想使其成為
      全局的,那么這個時候創(chuàng)建一個堆對象無疑是良好的選擇。
      由于堆和棧各有優(yōu)缺點,因此好多時候我們是將堆和棧結(jié)合使用的,比如在存儲一些較大數(shù)據(jù)的時候,我們將數(shù)據(jù)存放到堆中,
      卻將指向該數(shù)據(jù)的指針放在棧中,這樣就可以有效的提高程序的執(zhí)行速度,避免一些不該有的碎片。不過,一般來說,假如不
      是特大的數(shù)據(jù),我們都是使用棧,比如:函數(shù)調(diào)用過程中的參數(shù),返回地址,和局部變量都存放到棧中。這樣可以大大加快程
      序的運行速度。

使用指針保存內(nèi)存地址

由于每一個被定義的變量都有自己的地址,因此你完全可以使用指針來存放任何已被定義的變量的地址,即使它沒有被賦值

int main(){
  int i;
  //定義了一個指針p,星號(*)代表變量p是一個指針.要注意它的類型也是int
  int *p;
  //將i 的地址 賦值給p
  p=&i;
  return 0;
}

空指針

我們知道指針就是用來保存內(nèi)存地址的變量,因此我們定義一個指針后一定要用它來保存一個內(nèi)存地址,假如我們不那么做,那么該指針就是一個
失控指針,它可以指向任何地址,并且對該地址的數(shù)值進行修改或者刪除,后果是非??膳碌?解決辦法是將指針初始化為0

int main(){
  int *p;
  //將指針初始化為0 這樣指針p就不會因為我們的疏忽而隨意指向任意一個地址并且修改該地址的值。
  p=0;
  //空指針的地址 00000000;
  return 0;
}

指針和類型

由于不同類型的變量在內(nèi)存中所占用的字節(jié)不同,而指針又是用來保存內(nèi)存地址的變量,因此指針只能存儲與它類型相同變量的地址

int main(){
  //定義了一個雙精度型變量a.編譯器接到此定義通知后會在內(nèi)存中開辟一塊內(nèi)存區(qū)域.該區(qū)域的大小剛好可以存放雙精度型數(shù)值
  double a=3.14;
  //定義了一個指向整型變量的指針變量p.編譯器知道了指針指向的類型,才能對其進行正確的處理與運算。
  int *p1;
  int b=6;
  double *p2;
  p1=&b;
  p2=&a;
  
  count<<"p1:"<  count<"p2:"<  
  p1++;
  p2++;

  count<<"p1:"<  count<"p2:"<  return 0;
}
//經(jīng)過輸出發(fā)現(xiàn) 進行自加后 內(nèi)存地址進行了改變 int類型的內(nèi)存移動了4個字節(jié) double移動了8個字節(jié)
//由于指針的類型的不同決定了指針運算方式也不同,所以我們不能將一種類型的指針賦給另一種類型的指針

用指針來訪問值

運算符*被稱為間接引用運算符,當使用星號*時,就讀取它后面變量中所保存的地址處的值

例如:
int main(){
  int a=1;
  int *p=0;
  p=&a;
  //指針變量p前面的間接運算符*的含義是:"存儲在此地址處的值".*p的意思就是讀取該地址處的值.
  //由于p存儲的是a的地址,因此執(zhí)行的結(jié)果是輸出a的值:1.
  cout<<*p
}

指針對數(shù)值的操作

//沒什么難度 可看可不看
int main(){
  //簡化書寫類似于定義一個變量有某種特殊含義
  //這里的意思就是簡化short int的書寫方式為ut,即用ut就代表short int
  typedef unsigned short int ut;
  ut i=5;
  ut *p=0;
  p=&i;
  
  cout<<"i="<  cout<<"*p"<<*p<  cout<<"用指針來修改存放在i中的數(shù)據(jù) ";
  
  *p=90;
  cout<<"i="<  cout<<"*p"<<*p<  cout<<"用i來修改存放在i中的數(shù)據(jù) ";
  i=9;
  cout<<"i="<  cout<<"*p"<<*p<}

更換指針保存的地址

//沒什么難度 可看可不看
int main(){
  int i=0;
  int j=1;
  int *p=&i;
  count<<*p  p=&j;
  count<<*p}

指針和堆

  從文章開頭處的內(nèi)存棧堆的說明中可以了解到堆的好處是可以存儲比較大的數(shù)據(jù),而且存儲的數(shù)據(jù)只要不是程序員手動將其釋放那么就會永遠保
存到堆中,而棧存儲的數(shù)據(jù)只是在函數(shù)內(nèi)有效,超出函數(shù)就消失了,而全局標量保存的數(shù)據(jù)只有程序結(jié)束才會釋放,很容易被修改
  堆是一大堆不連續(xù)的內(nèi)存區(qū)域,在系統(tǒng)中由鏈表將它們串聯(lián)起來,它無法像棧那樣對其中的內(nèi)存單元命名,而系統(tǒng)為了數(shù)據(jù)隱秘,堆中的每個內(nèi)存單
元都是匿名的,因此你必須現(xiàn)在堆中申請一個內(nèi)存單元的地址,然后把它保存在一個指針中。這樣你只有使用該指針才可以訪問到該內(nèi)存單元的數(shù)據(jù)。
  采用這種匿名的內(nèi)存訪問方式,而不是使用公開的全局變量,好處是只有使用特定的指針才能訪問特定的數(shù)據(jù)。這樣就避免了任何試圖修改它的
非法操作
  要做到這一點,我們首先得創(chuàng)建一個堆,然后定義一個指向該堆的指針。這樣就只能通過該指針才能訪問堆中數(shù)據(jù)。
  在C++中使用關(guān)鍵字new創(chuàng)建一個堆并分配內(nèi)存,在new后面跟一個要分配的對象類型,編譯器根據(jù)這個類型來分配內(nèi)存。
  示例:
  int *p;
  p=new int;
  第一行定義了一個指向整型的指針變量p,第二行用new在堆中創(chuàng)建一個int類型的內(nèi)存區(qū)域,然后將該區(qū)域的內(nèi)存地址賦給指針變量p。這樣p所
指向的就是這塊新建的內(nèi)存區(qū)域。在這里要注意的是,new int在堆中被編譯器分配了4個字節(jié)的空間。假如是new double那么就要分配8個字節(jié)的
內(nèi)存空間。
  另外當如下寫時:
  int *p=new int;
  這樣在定義指針p的同時初始化了它的值為一個在堆中新建的int型存儲區(qū)的內(nèi)存地址。你可以像使用普通指針一樣使用它,并把賦值給它所指向
的內(nèi)存空間

  演示代碼如下:(使用指針訪問new 存儲區(qū))
  
  int main(){
    int *p;
    //new int當在內(nèi)存創(chuàng)建成功時返回值為內(nèi)存的地址,所以可以直接賦值給p
    p=new int;
    //將5賦值到了p所指向的內(nèi)存空間
    *p=5;
    cout<<*p;
    return 0;
  }

 最后需要注意的:
  由于計算機的內(nèi)存是有限的,因此可能會出現(xiàn)沒有足夠內(nèi)存而無法滿足new的請求,在這種情況下,new會返回0,該值被賦給指針后,那么該指針
  就是一個空指針,空指針不會指向有效數(shù)據(jù)。new除了返回空值外,還會引發(fā)異常,具體在后面的一場錯誤處理中在介紹。

 用指針刪除堆中空間

  由于使用new創(chuàng)建的內(nèi)存空間不會被系統(tǒng)自動釋放,因此假如你不去釋放它,那么該區(qū)域的內(nèi)存將始終不能為其他數(shù)據(jù)所使用,而指向該內(nèi)存
的指針是一個局部變量,當定義該指針的函數(shù)結(jié)束并返回時,指針也就消失了,那么我們就再也找不到該快內(nèi)存地址,我們把這種情況叫做內(nèi)存泄
漏。這種糟糕的情況將一直持續(xù)到程序結(jié)束該區(qū)域的內(nèi)存才能恢復使用。因此假如你不需要一塊內(nèi)存空間,那么就必須對指向它的指針使用關(guān)鍵
字delete.
  int main(){
    int *p=new int;
    //刪除指針指向的內(nèi)存空間
    delete p;
    p=new int;
    //刪除指針指向的內(nèi)存空間
    delete p;
    //注意不要delete兩次,加入再次刪除時雖然編譯不會報錯,但是運行時會造成程序崩潰
    //delete p; 這種做法是錯誤的
    return 0;
  }

  例2:(對內(nèi)存的總結(jié))
  main(){
    int *p=new int;
    *p=3600;
    cout<<*p<    delete p;
    //這里輸出了-572662307 這個數(shù)是不確定的 因為當我們將內(nèi)存釋放后,那么這塊內(nèi)存就會被其他程序所使用
    //所以當delete p后一定要將p清零,這樣可以防止造成錯誤操作
    cout <<*p<    //將p清零,防止造成錯誤操作。
    p=0;
    p=new int;
    *p=8;
    cout<<*p<    delete p;
    return 0;
  }
  如果以上代碼能看到并能正確的預測輸出結(jié)果,就代表你掌握了這快內(nèi)容哦^_^.

內(nèi)存泄漏

假如沒有刪除一個指針就對其重新賦值
例如:
int main(){
  int *p=new int;
  p=new int;
}
這樣就會造成內(nèi)存泄漏
因為第一行定義了一個指針p并使其指向一塊內(nèi)存空間,第二行又將一塊新的內(nèi)存空間的地址賦給了p,這樣第一行所開辟的那塊內(nèi)存空間就無法
再使用了,因為指向它的指針現(xiàn)在已經(jīng)指向了第二塊空間
指針變量p只能保存一個地址,對它重新賦值則表示以前的地址被覆蓋,加入該地址的內(nèi)存空間沒有被釋放,那么你將無法再次通過指針p訪問它.
因為此時的指針變量p記錄的是第二塊內(nèi)存的地址
所以為了避免內(nèi)存泄漏 在做第二個引用的時候要先 delete p;
假如暫時不想刪除第一塊內(nèi)存空間,那么你可以這么做:
int *p1=new int;
int *p2=new int;
分別用兩個指針來指向兩塊內(nèi)存空間,這樣每塊空間都有一個指針來指向,也就不會造成找不到某塊空間的內(nèi)存泄漏現(xiàn)象

在堆中創(chuàng)建對象

我們既然可以在堆中保存變量,那么也就可以保存對象,我們可以將對象保存在堆中,然后通過指針來訪問它。
例:
int main(){
  Human *p;
  p=new Human;
  return 0;
}
第一行定義了一個Human類的指針p,第二行使用new創(chuàng)建一塊內(nèi)存空間,同時又調(diào)用了Human類的默認構(gòu)造函數(shù)來構(gòu)造一個對象,它所占用的內(nèi)
存大小根據(jù)Human類對象的成員變量來決定,加入該類有兩個int型成員變量,那么該對象占用為2乘以4等于8個字節(jié).構(gòu)造函數(shù)一般都是在創(chuàng)建
對象時被自動調(diào)用,它的作用就是初始化該對象的成員數(shù)據(jù).本行的右半部分創(chuàng)建一個對象完畢后,跟著將該對象的內(nèi)存地址賦給左邊的指針變
量p

在堆中刪除對象

假如我們要刪除在堆中創(chuàng)建的對象,我們可以直接刪除指向該對象的指針,這樣會自動調(diào)用對象的析構(gòu)函數(shù)來銷毀該對象同時釋放內(nèi)存
例:
class Human{
  public:
    Human(){cout<<"構(gòu)造函數(shù)執(zhí)行中.. "; i=999;}
    ~Human(){cout<<"析構(gòu)函數(shù)執(zhí)行中... ";}
  private:
    int i;
};
int main(){
  Human *p=new Human;
  //跟釋放變量內(nèi)存寫法一樣,在對象中這樣寫調(diào)用的是函數(shù)的析構(gòu)函數(shù)
  delete p;
  return 0;
}

訪問堆中的數(shù)據(jù)成員

假如我們要訪問對象的數(shù)據(jù)成員和函數(shù),我們使用成員運算符"."。
例:
Human Jack;
Jack.i;
那么如何用指針操作呢?如下:
(*p).get();
p為對象的指針,使用括號是為了保證先使用*號讀取p的內(nèi)存地址中的值,即堆中對象,然后再使用成員運算符"."來訪問成員函數(shù)get()。
由于這樣做比較麻煩,因此c++專門為指針來間接訪問對象的成員設(shè)置了一個運算符: 成員指針運算符(->)。該符號可以實現(xiàn)讀取對象的內(nèi)存
地址并且訪問該對象的成員的作用。
因此:
  (*p).get(); 可以寫為 p->get();

在構(gòu)造函數(shù)中開辟內(nèi)存

我們可以將類的數(shù)據(jù)成員定義一個指針,然后在構(gòu)造函數(shù)中開辟新空間,將該空間的地址賦給指針.而在析構(gòu)函數(shù)中釋放該內(nèi)存
class Human{
  public:
    //int是一個整型,不是類對象,所以new int(999)不會調(diào)用構(gòu)造函數(shù),而是將999這個數(shù)值存儲到新建的內(nèi)存區(qū)域中
    //這樣就是在構(gòu)造函數(shù)中開辟一個新空間
    Human(){cout<<"構(gòu)造函數(shù)執(zhí)行中... ";i=new int(999);}
    //在析構(gòu)函數(shù)中釋放改內(nèi)存,防止造成內(nèi)存泄漏
    ~Human(){cout<<"析構(gòu)函數(shù)執(zhí)行中... ";delete i;}
    //*i是int類型
    int get(){return *i;}
  private:
    int *i;
}
//該例僅僅是為了說明構(gòu)造函數(shù)中也可以開辟堆中空間,在實際程序中,一個在堆中創(chuàng)建的對象通過成員指針再創(chuàng)建新空間用來保存數(shù)據(jù)并沒有
//什么意義。以為在堆中創(chuàng)建對象時已經(jīng)為它的所有數(shù)據(jù)成員提供了保存的空間

對象在棧和堆中的不同

例:
int main(){
  Human Jack;
  return 0;
}
一個存儲在棧中的對象,如:
Human Jack;
會在超出作用域時,比如說遇到右大括號,自動調(diào)用析構(gòu)函數(shù)來釋放該對象所占用的內(nèi)存。

而一個存儲在堆中的對象,如:
Human *Jack=new Human;
delete Jack;
則需要程序員自行對其所占用的內(nèi)存進行釋放.否則該對象所占用的內(nèi)存直到程序結(jié)束才會被系統(tǒng)回收

this指針

學生在發(fā)新課本時一般都要將自己的名字寫在課本上,以說明該課本是自己的,避免與別的學生混淆.同樣對象也要在屬于自己的每個成員身上
寫下自己的名字,以證明該成員是自己的成員,而不是別的對象的成員。this變量幫助對象做到這一點,this變量記錄每個對象的內(nèi)存地址,
然后通過間接訪問運算符->訪問該對象的成員。

例:
class A{
  public:
    //由于方法中i的值不需要改變,所以可以加修飾符const
    int get()const{return i;}
    void set(int x){i=x;cout<<"this變量保存的內(nèi)存地址: "<  private:
    int i;
};
int main(){
  A a;
  a.set(9);
  cout<<"對象a的內(nèi)存地址: "<<&a<  cout<  A b;
  b.set(999);
  cout<<"對象b的內(nèi)存地址: "<<&b<  cout<  return 0;
}
//通過打印的結(jié)果可以看出:
//this變量記錄每個單獨的對象的內(nèi)存地址,而this指針則指向每個單獨的對象.因此不同的對象輸出的this變量的內(nèi)存地址也不同
//在默認情況下this指針是不寫的。比如第七行 this-i=x; 假如我們寫i=x; 編譯器會自動在成員變量i前面加上this指針,用來表示這
//個i成員是屬于某個對象的。
//由于this指針保存了對象的地址,因此我們可以通過該指針直接讀取某個對象的數(shù)據(jù),它的作用將會在后面的重載運算符中得到演示,對于
//this指針的創(chuàng)建與刪除由系統(tǒng)(編譯器)來控制,所以我們不需要進行這方面的操作

指針的常見錯誤

1.刪除一個指針后一定要將該指針設(shè)置為空指針,因為刪除該指針只會釋放它所指向的內(nèi)存空間,不會刪除指針,因此這個指針還存在,并且它
依然會指向原來的內(nèi)存空間,因此這是如果你再次嘗試使用該指針,那么將會導致程序出錯。

指針的加減運算

指針可以進行加法運算

例:
int *p=new int;
p++;
將指針變量p中的內(nèi)存地址自加。由于p指向的是int型變量,因此執(zhí)行加1操作會將原來的內(nèi)存地址增加4個字節(jié)

p--;
概念跟++一樣,將內(nèi)存地址自減.

可以通過cout<
p=p-2;
"-2"后空間地址,因為是int型變量,因此執(zhí)行-2操作會將原來的內(nèi)存地址減8個字節(jié)。

 指針的賦值運算

指針也可以進行賦值運算,比如說將一個變量地址賦給另一個指針變量地址
int main(){
  int *p=new int;
  cout<<"p:"<  int *p1=new int;
  cout<<"p1"<  p=p1;
  cout<<"賦值后.. ";
  cout<<"p:"<  return 0;
}

指針的相減運算

用p-p1,將結(jié)果保存到p指向的內(nèi)存空間中,這樣p指向的內(nèi)存空間保存的就是p與p1的內(nèi)存地址差

指針的比較運算

兩個指針之間也可以進行比較運算。

 常量指針

定義常量指針:int *const p;這個指針它自身的值是不可以改變的,但是它指向的目標卻是可以改變的
例:
int main(){
  int a=3;
  int *const p=$a;
  cout<<"a:"<  a=4;
  cout<<"a:"<  return;
}
例2:
class A{
public:
  int get() const{return i;}
  void set(int x){i=x;}
private:
  int i;
};
int main(){
  A*p=new A;
  cout<<"p:"<  p=p+1;
  cout<<"p:"<  A *const p1=new A;
  //p1=p1+1; 這樣會報錯提示不可被改變
  p1->set(11);
  cout<get();
  return 0;
}
通過這個例子進一步說明了常量指針的特性,常量指針自身不可改變,但是它指向的目標卻可以改變.無論這個目標是變量還是對象。

  

 指向常量的指針

假如將上面例2中的 A*const p1=new A;寫為 const A* p1=new A;那么p1就變成了指向常量的指針,該指針指向的目標是不可修改的,但是該指針可以
被修改
指向常量的指針只是限制我們修改它指向的目標,它自身是可以被修改的.

指向常量的常指針

假如 const A* const p1=new A;這種寫法,則代表指向常量的常指針,它指向的目標是不可修改的,并且該指針也不可以被修改.

二級指針

//如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量為指針的指針變量,也稱為"二級指針" //通過指針訪問變量稱為間接訪問.由于指針變量直接指向變量,所以稱為"一級指針".而如果通過指向指針的指針變量來訪問變量則構(gòu)成"二級指針". 地址變量 變量 地址---------------> 值 指針變量1 指針變量2 變量 地址1------------>地址2------------>值

指針到這里就結(jié)束了,下一張介紹的為 "引用"


網(wǎng)站名稱:(四)指針-創(chuàng)新互聯(lián)
分享鏈接:http://fisionsoft.com.cn/article/egjdj.html