你知道纯C单链表跟C++单链表的区别吗?!引用传递和值传递以及链表中的LinkList L、LinkList *L、LinkList &L

您所在的位置:网站首页 双链表和单链表对比增加了什么 你知道纯C单链表跟C++单链表的区别吗?!引用传递和值传递以及链表中的LinkList L、LinkList *L、LinkList &L

你知道纯C单链表跟C++单链表的区别吗?!引用传递和值传递以及链表中的LinkList L、LinkList *L、LinkList &L

2023-07-14 22:30| 来源: 网络整理| 查看: 265

函数参数传递的两种方式为值传递和引用传递

1.传值方式传参

c语言是按值传递的,在函数中被传递的参数的本身(实参)是不能被修改的!参数x传进去的时候会被复制了一份copy,此后的修改都是在临时变量copy上,出了函数体copy被销毁,x还是原来的x,根本就没有被修改过,所以对变量x的修改无效。

如果想要修改传入的参数,有两种方法:

①传地址,传入x的地址,也就是将指向x的指针作为参数进行传递,【指针参数传递本质上是值传递,它所传递的是一个地址值】int f(int *x); f(&x); 指针传进去被复制了一份copy,x的指针的copy指向的内容也是x,对指针的copy的修改也就是修改了x的内容。 对于①来讲,在函数中如果传递的是指针,那么只能修改指针指向的内容,不能修改指针本身;如果想要修改指针本身,要么在再加一级指针,要么用引用&。

②引用传参 ,引用传参往往要比值传参高效,因为它是直接将x作为参数传入进去,而少了对x进行复制这部分的开销,既然传入进去的是x,那么对x的修改肯定也生效。

2.引用方式传参

引用可以被理解为变量的一个别名,但这依旧是原变量,如果在函数内对该变量进行修改的话,在外部该变量也会相应被修改。一定要先有原变量,才能有原变量的别名,故引用一定要赋初值,写成int &a=一个已存在的值的形式。

int a=11; int &b=a; b=9 在这时输出a的值发现a=9。

【比如:我的名字叫王**,**别名叫王哥,我在函数里传入的参数为王哥,在函数内部我修改了王哥的体重,那么在调用函数时,王****的体重也被修改了。】

引用声明后使用方式和原变量一样(用指针的话要加一个取值的操作)

**

3.通过一段代码运行进一步理解传指针(包括二级指针)和传指针的引用

**

①函数传递的是指针变量的值——即该指针所指向的变量的地址,只能改变指针所指向变量的值,而不能改变指针本身的值。

#include #include typedef struct LNode { int data;struct LNode *next; }LNode,*LinkList; void CreateList(LNode *header) { header=(LNode*)malloc(sizeof(LNode)); header->data=11; header->next=NULL; } int main() { LinkList head=NULL; CreateList(head); if(head!=NULL) printf("%d\n",head->data);//什么都没有输出 free(head); return 0; }

②传递指针的地址,便可以修改指针本身的内容

#include #include typedef struct LNode { int data; struct LNode *next; }LNode,*LinkList;//初始化链表,函数调用完毕后,L会指向一个空的链表,即会改变指针的值,所以要用**header //**header不仅能修改指针所指向变量的值,也能够修改指针本身的内容 void CreateList(LNode **header) { //(LinkList *header) (*header)=(LNode*)malloc(sizeof(LNode)); //(LinkList)malloc(sizeof(LNode)); (*header)->data=11; (*header)->next=NULL; } int main() { LinkList head=NULL; CreateList(&head); //传递指针本身的地址 if(head!=NULL) { printf("%d\n",head->data);//11 } free(head); return 0; }

③(LinkList &header)这里的header其实是传入指针head的别名

#include #include typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; //header其实是传入指针head的别名 void CreateList(LinkList &header){ //参数也可写成(LNode *&header) header=(LNode*)malloc(sizeof(LNode));//(LinkList)malloc(sizeof(LNode)); header->data=11; header->next=NULL; } int main(){ LinkList head=NULL; CreateList(head); if(head!=NULL){ printf("%d\n",head->data);//11 } free(head); return 0; } 4.总结

其实指针类型和基本类型(比如int)来说,并没有本质上的差别。示例 :int x;LNode *L; (LNode为结构体)

· 在传值方式传参时,对于基本类型:函数参数为int x,调用函数传入x;对于指针:函数参数为LNode *,调用函数时传入L

· 在地址传递时,对于基本类型:函数参数为int *x,调用函数传入&x;对于指针:函数参数为LNode **,调用函数时传入&L。

· 在引用方式传参,对于基本类型:函数参数为int &x,调用函数传入x;对于指针:函数参数为LNode* &L(或LinkList &L ),调用函数时传入&L。

当你传值时,只可以引用值而不可以改变值,但传值引用时,可以改变值; 当你传指针时,只可以改变指针所指的内容,不可以改变指针本身,但传指针引用时,即可以改变指针所指的内容,又可以改变指针本身

→补充注意点:

①在定义函数时函数括号中的变量名成为形式参数,简称形参或虚拟参数;在主调函数中调用一个函数时,该函数括号中的参数名称为实际参数,简称实参,实参可以是常量、变量或表达式。

②C语言中实参和形参之间的额数据传递是单向的“值传递”,单向传递,只能由实参传给形参,反之不能。

③被调用函数的形参只有函数被调用时才会临时分配存储单元,一旦调用结束占用的内存便会被释放。

④”按值传递“中包括值传递和指针传递(指针传递参数本质上是值传递的方式,它所传递的是一个地址值),传递的都是实参的一个拷贝;虽然指针传递可以通过改变地址值来改变指针所指向的变量的值,但是不能改变指针本身的值。

⑤对于指针的引用类似于二级指针,但是也有一定的区别:无论你传值还是传指针,函数都会生成一个临时变量, 但传引用时,不会生成临时变量,不进行返回值copy等,速度快。

⑥关于引用传递和指针传递(本质是值【地址值】传递):

· 相同点:都是地址的概念

指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

· 不同点:

· 指针是一个实体(也可以理解为替身);引用只是一个别名(本体的另一个名字)

· 引用只能在定义时被初始化一次,之后不可改变;指针可以修改;

· 引用不能为空;指针可以为空;

· sizeof 引用,得到的是所指向变量的大小;sizeof 指针,得到的是指针的大小;

· 指针 ++,意义为 指针的地址自增;引用++则是 所指变量自增;

· 引用是类型安全的,引用过程会进行类型检查;指针不会进行安全检查;

5、下面附上单链表的C语言实现与C++实现,你可以去比较比较

单链表的C++实现 样例输入

Empty Insert 1 7 Empty Insert 2 3 Length Insert 1 -100 Length Insert 10 100 Length Insert 2 10000 Empty GetElem 2 GetElem 5 LocateElem 999 LocateElem 3 Delete 0 Delete 4 Delete 1 Length

样例输出

Empty 7 Not empty 7 3 List length is 2 -100 7 3 List length is 3 Insert failed List length is 3 -100 10000 7 3 Not empty The elem at position 2 is 10000 Out of index 999 is not found in list 3 is found at the position 4 Delete failed -100 10000 7 10000 7 List length is 2 #include #include #include using namespace std; ​ #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; //Status 是函数返回值类型,其值是函数结果状态代码。 ​ typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型 ​ #define MAXSIZE 100 //链表可能达到的最大长度 ​ typedef struct LNode { ElemType data; //结点的数据域 struct LNode* next; //结点的指针域 } LNode, * LinkList; //LinkList为指向结构体LNode的指针类型 ​ Status InitList(LinkList& L) //算法2.6 单链表的初始化 { //构造一个空的单链表L L = new LNode; //生成新结点作为头结点,用头指针L指向头结点 L->next = NULL; //头结点的指针域置空 return OK; } ​ Status DestroyList(LinkList& L) { /* 初始条件:线性表L已存在。操作结果:销毁线性表L */ LinkList q; while (L) { q = L->next; delete L; L = q; } return OK; } ​ int ListLength(LinkList L) { ​ LinkList a = L; int count = 0; while (a->next) { a = a->next; count++; } return count; ​ } ​ bool ListEmpty(LinkList L) { ​ if (!L->next) return 1; return 0; ​ } ​ Status GetElem(LinkList L, int i, ElemType& e) //算法2.7 单链表的取值 { ​ if (iListLength(L)) return ERROR; LinkList l=L; while(l&&i--) { l = l->next; } e = l->data; return OK; ​ } //GetElem ​ int LocateElem(LinkList L, int e) //略有改动 算法2.8 按值查找 { ​ LinkList l = L->next; int count = 0; while (l) { if (l->data == e) return count + 1; l = l->next, count++; } return 0; ​ } //LocateElem ​ Status ListInsert(LinkList& L, int i, ElemType e) //算法2.9 单链表的插入 { ​ if (iListLength(L) + 1) return ERROR; LinkList a = L; LNode* b; b = (LNode*)malloc(sizeof(LNode)); while(--i&&a) a = a->next; b->data = e; b->next = a->next; a->next = b; ​ return OK; ​ } //ListInsert ​ Status ListDelete(LinkList& L, int i) //算法2.9 单链表的删除 { ​ if (iListLength(L)) return ERROR; LinkList l = L; LNode* b; ​ while (l && --i) l = l->next; if (!l->next) return ERROR; ​ b = l->next; l->next = b->next; delete b; return OK; ​ } //ListDelete ​ void ListPrint(LinkList L) { LNode* p; for (p = L->next; p; p = p->next) cout if (op == "Empty") cout cout cin >> e; i = LocateElem(L, e); if (i == 0) cout ElemType data; //结点的数据域 struct LNode* next; //结点的指针域 } LNode, * LinkList; //LinkList为指向结构体LNode的指针类型 ​ Status InitList(LinkList *L) //单链表的初始化 { //构造一个空的单链表L *L=(LinkList)malloc(sizeof(LNode));//生成新结点作为头结点,用头指针L指向头结点 (*L)->next = NULL; //头结点的指针域置空 return OK; } ​ Status DestroyList(LinkList *L) { /* 初始条件:线性表L已存在。操作结果:销毁线性表L */ LinkList q; while (*L) { q = (*L)->next; free(*L); *L = q; } return OK; } int ListLength(LinkList L) { LNode* a = L; int length = 0; while (a->next) { a = a->next; length++; } return length; } ​ int ListEmpty(LinkList L) { if (!L->next) return 1; return 0; } ​Status GetElem(LinkList L, int i, ElemType *e) //单链表的取值 { if (iListLength(L)) return ERROR; while(L&&i--) { L = L->next; } *e = L->data; return OK; } //GetElem ​ int LocateElem(LinkList L, int e) //按值查找 { LNode *p= L; int count = 0; while (p) { if (p->data == e) return count; p = p->next, count++; } return ERROR; } //LocateElem ​ Status ListInsert(LinkList *L, int i, ElemType e) // 单链表的插入 { if (iListLength(*L) + 1) return ERROR; LinkList a = *L; LinkList b; b = (LinkList)malloc(sizeof(LNode)); while(--i&&a) a = a->next; if(!a) return ERROR; b->data = e; b->next = a->next; a->next = b; ​ return OK; } Status ListDelete(LinkList *L, int i) //算法2.9 单链表的删除 { ​ if (iListLength(*L)) return ERROR; LNode *l = *L; LNode *b=(*L)->next; ​ while (l && --i) l = l->next; if (!l->next) return ERROR; ​ b = l->next; l->next=b->next; free(b); return OK; ​} void ListPrint(LinkList L) { LNode *p; p=L->next; while(p) { printf("%d%c", p->data, p->next ? ' ' : '\n'); p=p->next; } } ​int main() { int i; ElemType e; LinkList L; char op[20]; InitList(&L); while (~scanf("%s",op)) { if (strcmp(op,"Empty")==0) { if(ListEmpty(L)) printf("Empty\n"); else printf("Not empty\n"); } else if (strcmp(op,"Insert")==0) { scanf("%d %d",&i,&e); if (ListInsert(&L, i, e) == ERROR) printf("Insert failed\n"); else ListPrint(L); } else if (strcmp(op,"Length")==0) { printf("List length is %d\n",ListLength(L)); ​} else if (strcmp(op,"GetElem")==0) { scanf("%d",&i); if (GetElem(L, i, &e) == ERROR) printf("Out of index\n"); printf("The elem at position %d is %d\n",i,e); } else if (strcmp(op,"LocateElem")==0) { scanf("%d",&e); i = LocateElem(L, e); if (i == 0) printf("%d is not found in list\n",e); else printf("%d is found at the position %d\n",e,i); } else if (strcmp(op,"Delete")==0) { scanf("%d",&i); // cin >> i; if (ListDelete(&L, i) == ERROR) printf("Delete failed\n"); else ListPrint(L); } } DestroyList(&L); return 0; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3