C++中引用的本质分析

2019-05-22 06:26:49来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

1,引用的意义:

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

       1,变量的另一个表现形式;

       2,交换函数时,可代替指针;

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

       1,指针类似手动挡车,引用类似于自动挡车;

    3,引用实现交换函数;

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

           1,调用函数的时候才初始化;

          

2,const 引用:

    1,代码示例:

1 int a = 4;
2 const int& b = a;
3 int* p = (int*)&b;  // 等价于取 a 的地址;
4 
5 b = 5;  // Error,只读变量;
6 *p = 5;  // Ok,修改变量 a 的值;

    2,在 C++ 中可以声明 const 引用;

    3,const Type& name = var;

       1,只有这样一种方式,不想 const 指针有四种方式;

    4,const 引用让变量拥有只读属性;

       1,引用对象是常量还是变量可以决定其所能参与的操作,但对于引用本身         是不是一个常量未做限定;

       2,因为引用对象可能是个非常量,所以允许通过其他途径改变它的值;

      

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

    1,代码示例:

const int& b = 1;  // Ok,产生空间,值为 1,别名为 b,生成只读变量;
       
int* p = (int*)&b;

b = 5;  // Error,只读变量;
*P = 5;  // Ok,修改变量 a 的值;

       1,这个分配的空间的别名是一个临时变量;

    2,结论:

       1,使用常量对 const 引用初始化后将生成一个只读变量;

   

4,引用的特殊意义实例分析:

    1,main.cpp 文件:

 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;  // error: assignment(赋值) of read-only reference 'b';
12     
13     *p = 5;
14     
15     printf("a = %d\n", a);  // a = 5;
16     printf("b = %d\n", b);  // b = 5;
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;  // error: assignment(赋值) of read-only reference 'b';
27     
28     *p = 5;
29     
30     printf("c = %d\n", c);  // c = 5;
31 }
32 
33 int main(int argc, char *argv[])
34 {
35     Example();
36     
37     printf("\n");
38     
39     Demo();
40 
41     return 0;
42 }

    2,结论:

  1,要使一个已经存在的变量拥有只读属性,变成只读变量,定义一个        const 引用即可;

 

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

    1,代码示例:

1 struct TRef
2 {
3     char& r;
4 };
5 
6 printf("sizeof(TRef) = %d\n", sizeof(TRef));

   

6,引用的思考编程实验:

    1,main.cpp 文件:

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

   

7,引用在 C++ 中的内部实现是一个指针常量:

    1,Type& name <==> Type* const name;

    2,void f(int& a)                       void f(int* const a)

         {                                          {

            a = 5;               <==>               *a = 5;  // 内部实现是这样;

         }                                         }

    3,C++ 编译器在编译过程中用指针常量作为引用的内部实现,因此引用所占用     的空间大小与指针相同;

    4,从使用的角度,引用只是一个别名,C++ 为了实用性而隐藏了引用的存储空     间这一细节;

   

8,引用的存储空间:

    1,main.cpp 文件:

 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));  // 12;
19     printf("sizeof(r.before) = %d\n", sizeof(r.before));  // 4;
20     printf("sizeof(r.after) = %d\n", sizeof(r.after));  // 4;
21     printf("&r.before = %p\n", &r.before);  // 0xbf8a300c;
22     printf("&r.after = %p\n", &r.after);  // 0xbf8a3014;
23 
24     return 0;
25 }

   

9,C++ 中的引用旨在大多数情况下代替指针:

    1,功能性:可以满足多数需要使用指针的场合;

    2,安全性:可以避开由于指针操作不当而带来的内存错误;

    3,操作性:简单易用,又不失功能强大;

   

10,函数返回引用实例分析:

    1,main.cpp 文件:

 1 #include <stdio.h>
 2 
 3 int& demo()  // int* const demo()
 4 {
 5     int d = 0; // warning: reference to local variable 'd' returned;
 6     
 7     printf("demo: d = %d\n", d);  // d = 0;
 8     
 9     return d;  // return &d;,返回局部变量地址是不可以的;
10 }
11 
12 int& func()
13 {
14     static int s = 0;
15     
16     printf("func: s = %d\n", s);  // s = 0;
17     
18     return s;//这里是可以的;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);  rd = 1320958828     printf("main: rs = %d\n", rs);  rs = 029     printf("\n");
30     
31     rd = 10;  // 对栈上已经释放的四个字节进行操作赋值,没意义;
32     rs = 11;
33     
34     demo();  // d = 0; 每次调用都会被重建;
35     func();  // s = 11;
36     
37     printf("\n");
38     printf("main: rd = %d\n", rd);  // rd = 13209588;
39     printf("main: rs = %d\n", rs);  // rs = 11;
40     printf("\n");
41     
42     return 0;
43 }

   1,引用能在最大程度上避开内存操作错误,但是不能够寄希望于完全避    免,因为它本质是指针;

   

11,小结:

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

    2,const 引用可以使得变量只有只读属性;

       1,可以避开误对变量赋值;

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

    4,引用的最终本质为指针;

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


原文链接:https://www.cnblogs.com/dishengAndziyu/p/10902803.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:写了一个工具分析基金回撤,分享实现过程

下一篇:HUST 1583 长度单位