最近在学习Golang的过程当中,发现一个有意思的事情,有的文章说函数调用传参时 slice 是引用传递,有的说是值传递。为何同一个东西你们会不一样认识?为了搞清楚其本质,我进行了如下内容的研究:c++
为了不文章写的过长,看了想瞌睡,分红两篇文章来解释这个问题,本文先解决问题1跟2,下一篇说明余下的问题。程序员
上学的时候,老师讲变量是存在内存中的,内存就像一排排抽屉组成的,每一个抽屉上面有个编号,咱们定义一个变量,就是把想放的东西放到这个对应编号的抽屉里。好比: int a = 10,用图来表示下:shell
这里:变量的名字叫 a ,变量的值是:10,变量的地址是:0x 00000001。
那么问题来了,变量的值咱们知道是放在了抽屉里(内存中),每一个抽屉有编号(地址),可是变量的名字 a 存放在哪里呢?或者说它会存在于内存中吗?函数
你们想一个问题,若是变量的名字要存放在内存中,那么确定分配一个空间给他,保存它的空间有个地址,这个地址是否是又得有个地方存起来程序才能找到?若是真是这样设计,那么代码根本没发写、没法运行了。学习
其实变量名仅仅是写给程序员看的,让咱们写代码的时候知道这个变量有什么用,可以经过名字调用变量的值。由于若是直接给你一个地址 0x 23004123,你知道这是要干吗吗?代码通过编译后,最终都会转换成机器码,咱们定义的变量名就都不存在了,存在的只有地址跟值。spa
有了上面的理解,再来一个特殊的变量:指针变量。什么叫指针变量呢?其实就是这个变量里边存放的是一个变量的地址,经过这个地址,机器能够找到对应变量的值,例如:int pa = &a,就表示变量 pa 抽屉里放的是 a 的地址,它的类型是:int,继续看图:设计
这里须要重要说明的是:指针pa与a的关系是:a抽屉里边放的是变量值10,pa放的是变量的地址:0x00000001,这里必定要记住,下面说引用的时候才更容易理解。指针
继续谈引用,引用与指针咱们常常傻傻分不清,由于它们的行为确实很是诡异,看起来效果很是类似,看代码:code
因为引用的概念是在 c++ 中引入的,所以下面的代码使用c++,仅仅是一些打印而已,放心看下去
int main() { int a = 10;// 变量 int * pa = &a; // 指针 int & b = a; // 引用 printf("a: %d\n", a);// a: 10 printf("*pa: %d\n", *pa);// *pa: 10 printf("b: %d\n", b);// b: 10 *pa = 20; printf("a: %d\n", a);// a: 20 printf("*pa: %d\n", *pa);// *pa: 20 printf("b: %d\n", b);// b: 20 b = 30; printf("a: %d\n", a);// a: 30 printf("*pa: %d\n", *pa);// *pa: 30 printf("b: %d\n", b);// b: 30 a = 40; printf("a: %d\n", a);// a: 40 printf("*pa: %d\n", *pa);// *pa: 40 printf("b: %d\n", b);// b: 40 return 0; }
经过上面的代码咱们发现,指针与引用都能达到一个效果:都有能力修改a的值,指针前面讲过了,由于它保存了a的地址,经过解引用操做后,实际上就是打开了a的抽屉,所以能够进行修改。那么引用又是怎么办到的?这里注意一个细节:pa = 20; c = 30;a = 40。咱们看到操做c的时候与操做a是同样的方式:直接使用变量名,可是pa要想改变a的值,必须进行 pa 操做(解引用),若是直接 pa=20,这仅仅是改变的pa的值,让他指向了另一个地址。blog
为何引用与变量是同样的操做方式?先来看一下引用的定义:
引用就是某一变量的一个别名,对引用的操做与对变量直接操做彻底同样。
那么别名是什么意思呢?继续看图,一看就懂
看到了吧?a就是b,b就是a。系统并不会为引用额外分配空间进行存储,甚至能够简单理解为:这个别名仅仅是为了给程序员看的,到机器码层面的时候,他们都会变成地址:0x 00000001。
经过上面的分析不知道你理解了几分?或者你是否是对指针与引用仍是半信半疑?不要紧,写点代码证实一下便可,咱们要证实的是:
为了证实,程序设计以下:定义一个变量,分别赋值给指针、引用,而后检查他们对应的值与地址。
int main() { int a = 10; printf("%d\n", a); printf("%p\n", &a); printf("~~~~~~~~~~~~~~\n"); int * b = &a; printf("%p\n", b); printf("%p\n", &b); printf("~~~~~~~~~~~~~~\n"); int & c = a; printf("%d\n", c); printf("%p\n", &c); return 0; }
得到输出:
10 // 变量a的值 0x7ffee3c7a768 // 变量a的地址
0x7ffee3c7a768 // 指针的值,是变量a的地址
0x7ffee3c7a760 // 指针变量本身的地址
10 // 变量a的值 0x7ffee3c7a768 // 引用变量c的地址,与变量a的地址彻底同样
在上面若是指针想要打印变量a的值,须要解引用操做:printf(“%dn”, *b);
下次预告: