天天看點

關于鍊式結構中指針和引用的一些解釋

typedef struct node {  
    SElemType data;  
    struct ndoe *link;   
}LinkNode, *LinkStack;  
   
void InitStack(LinkStack &S) {  
    S=NULL;  
}  
           

解釋:

1. 因為有 typedef , 是以這裡的 LinkNode 相當于 struct node, *LinkStack相當于 struct node *;

     而在主函數裡用LinkStack S, 而不是LinkNode S.

2. 因為在開頭的時候這個linkStack确實是一個單純的結構體指針, 用來指向即将建立的鍊棧的首位址,用來代指對整鍊的引用

      其形式就相當于 char *a 建立一個數組, a 表示數組的首位址,代表對整個數組。

而凡是指針就需要初始化,這裡LinkStack S 初始化的方式是通過函數
void InitStack(LinkStack &S) {  
          S=NULL;  
}  
即将指針全部變成NULL,這也是一種合理的常用的初始化數組的手段。
           

其次這裡的(LinkStack &S) 表示的不是二級指針,切記不是二級指針

引用和指針式不同的。

關于引用的詳細解釋和指針的差別:

引用(reference)不是新定義一個變量, 而是給已存在的對象取了 一個别名 ,

引用類型,引用另外一種類型。 編譯器不會為引用對象新開辟記憶體空間, 它和它引用的對象共用同一塊記憶體空間 。

一般在初始化變量時,初始值會被拷貝到建立的對象中。然而定義引用時程式把引用和他的初始值綁定在一起,

而不是将初始值拷貝給引用。一旦初始化完成引用家将和他的初始對象一直綁定在一塊。

因為無法将引用重新綁定到另外一個對象上,是以引用必須初始化。

引用即别名。

引用并非對象,相反的,它隻是為一個已經存在的對象所起的另外一個名字。

定義一個引用之後,對其進行的所有操作都是在與之綁定的對象上進行的:

為引用指派,實際上是把值賦給了與引用綁定的對象。擷取引用的值,實際上是擷取了與引用綁定的對象的值。同理,以引用作為初始值,實際上是以引用綁定的對象作為初始值。

  引用的定義

   1. 允許在一條語句中定義多個引用,其中每個引用辨別符都必須以&開頭;

   2.因為無法将引用重新綁定到另外一個對象上,是以引用必須初始化。

   3.因為引用本身不是一一個對象,是以不能定義引用的引用。

   4.一個變量可以有多個引用,而一個引用隻能給一個變量對象 。

   5.引用的類型要和與之綁定的對象嚴格比對(不嚴謹)。

   6.引用隻能綁定在對象上而不能和字面值或某個表達式計算的記過綁定在一起。

引用與指針

相同點:

   底層的實作方式相同, 都是按照指針的方式來實作的:

 不同點:

1.有空指針,沒有空引用;

2.引用定義時必須初始化, 指針可以不用, 正常情況下需初始化為NULL;

3.引用一旦定義就不能再改變, 指針可以;

4.sizeof求取的值不一樣;

eg: int a;  int& b=a, int *p=&a;

sizeof(a)=4,   sizeof(b)=4, sizeof(p)=8;

引 用結果為引 用類型的大小,但指針始終是位址空間所占位元組個數。

指針不同于一般變量,存的是變量的位址,在同一架構下位址長度都是相同的(cpu的最大尋址記憶體空間

是以不同類型的指針長度都一樣,在64為的條件下就是8,這也就解釋了上文為什麼是sizeof(p)=8;

5.自 ++含義不同;

引用的自增對原變量的加一,指針表示對于指針位址加一個類型位元組大小,在數組裡是表示數組為加一,但指針若不是表示數組

首位址,那麼自增之後的位址空間就是不确定的。

6.可以有多級指針, 但是沒有多級引 用;

7.指針和引用的位址不同;

8.int**/ int&&意義不同;

使用指針和引用的意義:

C語言中函數有兩種傳參的方式: 傳值和傳址。以傳值方式, 在函數調用過程中會生成一份臨時變量用形參代替

, 最終把實參的值傳遞給新配置設定的臨時變量即形參。 它的優點是避免了函數調用的副作用, 但無法改變形參的值。

如果要改變實參的值, 隻 能通過指針傳遞。

通過指針和引用還節省了空間,因為如果資料類型太大的話,函數調用過程中實參複制到形參要浪費不少空間。

使用指針和引用即使直接對自身進行操作了。

(LinkStack &S) ,再次回到這裡。

這裡的 LinkStack& 表示對S的引用,  LinkStack& 總體是一個類型,因為主函數裡的 LinkStack S, S的類型時LinkStack的,

是以這裡的引用類型就必須是LinkStack的。并不是什麼二級指針。

關于二叉樹中的參數的一些解釋

typedef struct Node {//定義二叉樹結構
    char data;
    struct Node *lchild,*rchild;
}*BiTree,BiTNode;

void CreateBiTree(BiTree &T) {//先序建立二叉樹
    char ch;
    cin>>ch;
    if(ch=='#') T=NULL;
    else{
        T=new BiTNode;
        T->data=ch;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}
           

這裡的T是二叉樹連結清單的首位址。

疑問在于CreateBiTree(BiTree &T) 和下面函數裡的遞歸CreateBiTree(T->lchild)中的實參和形參怎麼對應。

解釋:

CreateBiTree(BiTree &T) 是一個引用,而不是二級指針,

如果要想T->lchild和他形參對應,那麼T->child就應該是BiTree類型的。

因為T->lchild表示的T指向的結構體的lchild,而在

BiTree結構體中對于左右孩子的定義是 struct node *lchild ,是BiTree類型的。

是以實參和形參是對應的。

最後,關于結構體變量。

typedef struct node {
    int data;
    struct node *link;
}Node;
Node *LinkNode;
           

-> 符号表示的是 (*LinkNode).data,   或者,(*LinkNode).link;

寫成LinkNode->data,   LinkNode->link;

注意這裡的link  和 data 一樣都是變量。 data 是 int 類型的,  link  是  struct node*類型的;

指針是位址, 指針變量是儲存位址的變量。兩者意義是不同的。

還有 int *p;

和 cout<<*P<<endl;

中的*  不是同一個符号;

int *p;叫做指針表示符,證明他是一個指針;

而後面的cout<<*p 中的*  意思是取指針值符号,意思是取p所指向的位址中的值;

就像加号和正号,表示的含義不同,但是符号相同一樣。

p 從始至終就是一個位址。

就醬吧,這是在學習過程中,自己不斷反思,總結的,對連結清單的一些東西應該來說扣的比較細了。

也很好的加深了自己對于指針的了解。

繼續閱讀