天天看点

关于链式结构中指针和引用的一些解释

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 从始至终就是一个地址。

就酱吧,这是在学习过程中,自己不断反思,总结的,对链表的一些东西应该来说扣的比较细了。

也很好的加深了自己对于指针的理解。

继续阅读