c++ reference研究
1赞c++相比于c语言,增加引用(reference)语法。这样的话,可以在函数调用,传引用,也可以实现函数内部修改外部参数值。而避免使用指针。
之前,对这个引用,没有特别的理解,但是看了侯捷老师的视频之后,会这个突然就恍然大悟了。
视频链接如下:
https://www.bilibili.com/video/av27135524?p=28
侯捷老师,在讲解引用时,有提到,引用,就是漂亮的指针。功能和指针一样,但是使用起来更漂亮。
我们在写程序时,一般会认为,对于一个变量,会分配内存空间,对于引用定义的变量,我们也认为会分配内存空间。
比如如下代码:
int a = 5; int &b = a; int &c = b; |
定义了3个变量,a,b,c,其中b和c是通过引用定义的。我们一般认为,编译器,会为a,b,c三个变量,都分配内存空间,然后通过特殊的操作,使的三个变量的操作,均是一致的。
但是,侯捷老师讲解到,对于引用定义的变量,其实并没有分配内存空间,使用的地址,和引用的变量是同一个地址。其实引用变量,就是被引用变量的一个别名。但是,它却给我们了一种,会为引用定义变量,分配的空间的这样一种假象。
侯捷老师,在这里原话解释是:
object(引用定义变量)和其reference的大小相同,地址也相同(全都是假象) |
因此,可以通过下面这个代码,进行印证。
int test(int a) { printf("test a address: %x\n", &a); return 0; }
int test1(int& a) { printf("test1 a address: %x\n", &a); return 0; }
int main() { int a = 5; int &b = a; int &c = b; printf("a address: %x\n", &a); printf("b address: %x\n", &b); printf("c address: %x\n", &c); test(a); test1(a); } |
在main函数中,定义了a,b,c三个变量,其中b和c是引用定义的变量,均引用到a。
将a,b,c的地址,打印出来。
a address: 6dfef4 b address: 6dfef4 c address: 6dfef4 |
从打印输出,可以看出,a,b,c三个变量的地址其实是一样的。正是因为他们的地址是一样的,所以对其中任意一个操作,也同样改变了其他的变量。所以,编译器,对于引用定义的变量,并不会分配内存空间,而是直接使用引用变量的内存地址空间。
下面看一下函数参数,传递为变量,和引用的却别。
int test(int a) { printf("test a address: %x\n", &a); return 0; } int test1(int& a) { printf("test1 a address: %x\n", &a); return 0; } int main() { int a = 5; printf("a address: %x\n", &a); test(a); test1(a); } |
test函数,传递的是变量,test1函数,传递的是引用。
在函数内部,分别将参数的地址给打印出来。
打印结果如下:
a address: 6dfefc test a address: 6dfee0 test1 a address: 6dfefc |
可以看出,函数参数传引用的话,那么该引用变量的地址,和外部传参变量的地址是一样的,所以这也是为什么,函数传递引用,在函数内部读该引用变量修改,就可以直接修改外部传参变量的值。因为,他们就是操作的同一片地址空间。
侯捷老师,在课程中一直提到,在c++中,函数参数传递,尽量使用引用,因为这会比较快。
原因就在于,传递引用,编译器只是将地址传递过去,如果是传递参数,那么编译器,会为参数分配一个新的内存空间,然后把传递参数的值,原封不动的拷贝进去,这样的话,效率就低了。如果是一个简单类型变量,那还能接受,如果是一个结构体,或者是个类,那么这里的拷贝,可能就会降低效率了。
所以对于引用的理解,就认为引用,就是原变量的别名就好。他们的地址空间完全一致。