引用作为变量别名而存在,因此在一些场合可以代替指针

引用相对于指针来说具有更好的可读性和实用性

swap函数的实现对比如下:

 

注意:

  函数中的引用形参不需要进行初始化。

示例程序如下:

 

形参没有初始化,而是在第15行调用的时候对引用形参进行初始化。

 const引用:

 

当使用常量对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名。

例:

 

结论:

  使用常量对const引用初始化后将生成一个只读变量。普通引用不能使用常量值进行初始化,但是const引用可以。

我们不能直接改变const引用的值,但是可以通过取地址的方式间接的改变这块内存的值。

示例程序:

 

 1 #include <stdio.h>
 2 
 3 void Example()
 4 {
 5     printf("Example:\n");
 6     
 7     int a = 4;
 8     const int& b = a;
 9     int* p = (int*)&b;
10     
11     //b = 5;
12     
13     *p = 5;
14     
15     printf("a = %d\n", a);
16     printf("b = %d\n", b);
17 }
18 
19 void Demo()
20 {
21     printf("Demo:\n");
22     
23     const int& c = 1;
24     int* p = (int*)&c;
25     
26     //c = 5;
27     
28     *p = 5;
29     
30     printf("c = %d\n", c);
31 }
32 
33 int main(int argc, char *argv[])
34 {
35     Example();
36     
37     printf("\n");
38     
39     Demo();
40 
41     return 0;
42 }

 

运行结果如下:

  可以看到Example函数中通过指针p可以改变内存空间的值,最终影响到了a和b的值,其实它们指的是同一块内存空间,在这个函数中我们也可以直接改变a的值。因为a并不是const的。

 引用有自己的存储空间吗?

 

示例程序如下:

 1 #include <stdio.h>
 2 
 3 struct TRef
 4 {
 5     char& r;
 6 };
 7 
 8 int main(int argc, char *argv[])
 9 { 
10     char c = 'c';
11     char& rc = c;
12     TRef ref = { c };
13     
14     printf("sizeof(char&) = %d\n", sizeof(char&));
15     printf("sizeof(rc) = %d\n", sizeof(rc));
16     
17     printf("sizeof(TRef) = %d\n", sizeof(TRef));
18     printf("sizeof(ref.r) = %d\n", sizeof(ref.r));
19 
20     return 0;
21 }

执行结果:

 

char&代表char的引用,所以占用一个字节,rc也是char的引用,占用一个字节,ref.r是char的引用,也占用一个字节。

sizeof(TRef)占用四个字节,这让我们联想到了指针。

引用的内部实现:引用在C++中的内部实现是一个指针常量,具体如下。

 

 引用的存储空间:

示例程序:

 1 #include <stdio.h>
 2 
 3 struct TRef
 4 {
 5     char* before;
 6     char& ref;
 7     char* after;
 8 };
 9 
10 int main(int argc, char* argv[])
11 {
12     char a = 'a';
13     char& b = a;
14     char c = 'c';
15 
16     TRef r = {&a, b, &c};
17 
18     printf("sizeof(r) = %d\n", sizeof(r));
19     printf("sizeof(r.before) = %d\n", sizeof(r.before));
20     printf("sizeof(r.after) = %d\n", sizeof(r.after));
21     printf("&r.before = %p\n", &r.before);
22     printf("&r.after = %p\n", &r.after);
23 
24     return 0;
25 }

执行结果如下:

 

根据计算,可以得到结构体中的ref占用了4个字节。从地址的判断也可以得出ref占用了4个字节。

 上述程序在windows下的反汇编如下:

 

引用的意义:

 

函数返回引用示例程序如下:

 1 #include <stdio.h>
 2 
 3 int& demo()
 4 {
 5     int d = 0;
 6     
 7     printf("demo: d = %d\n", d);
 8     
 9     return d;
10 }
11 
12 int& func()
13 {
14     static int s = 0;
15     
16     printf("func: s = %d\n", s);
17     
18     return s;
19 }
20 
21 int main(int argc, char* argv[])
22 {
23     int& rd = demo();
24     int& rs = func();
25     
26     printf("\n");
27     printf("main: rd = %d\n", rd);
28     printf("main: rs = %d\n", rs);
29     printf("\n");
30     
31     rd = 10;
32     rs = 11;
33     
34     demo();
35     func();
36     
37     printf("\n");
38     printf("main: rd = %d\n", rd);
39     printf("main: rs = %d\n", rs);
40     printf("\n");
41     
42     return 0;
43 }

  demo函数中相当于返回了局部变量的“指针”,这是有问题的。返回局部变量的引用是要禁止的。func函数中返回的是静态变量的引用。静态变量的存储空间不会由于函数调用的返回而被摧毁,因此,这样做是没有问题的。

执行结果如下:

 

第一次打印rd的值发生了很大的变化,这是因为26行函数的调用,改变了栈空间中的数据。第二次打印rd同理。

小结:

  引用作为变量别名而存在旨在代替指针

  const引用可以使得变量具有只读属性

  引用在编译器内部使用指针常量实现

  引用的最终本质为指针

  引用可以尽可能的避开内存错误

 

posted on 2018-08-21 23:12  周伯通789  阅读(266)  评论(0编辑  收藏  举报