zoukankan      html  css  js  c++  java
  • C++中引用的本质分析

    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:
    ");
     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
    ", a);  // a = 5;
    16     printf("b = %d
    ", b);  // b = 5;
    17 }
    18 
    19 void Demo()
    20 {
    21     printf("Demo:
    ");
    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
    ", c);  // c = 5;
    31 }
    32 
    33 int main(int argc, char *argv[])
    34 {
    35     Example();
    36     
    37     printf("
    ");
    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
    ", 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
    ", sizeof(char&));  // 1;这里求对应的变量大小;
    15     printf("sizeof(rc) = %d
    ", sizeof(rc));  // sizeof(rc) => 1;
    16     
    17     printf("sizeof(TRef) = %d
    ", sizeof(TRef));  // 4;
    18     printf("sizeof(ref.r) = %d
    ", 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
    ", sizeof(r));  // 12;
    19     printf("sizeof(r.before) = %d
    ", sizeof(r.before));  // 4;
    20     printf("sizeof(r.after) = %d
    ", sizeof(r.after));  // 4;
    21     printf("&r.before = %p
    ", &r.before);  // 0xbf8a300c;
    22     printf("&r.after = %p
    ", &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
    ", 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
    ", 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("
    ");
    27     printf("main: rd = %d
    ", rd);  rd = 1320958828     printf("main: rs = %d
    ", rs);  rs = 029     printf("
    ");
    30     
    31     rd = 10;  // 对栈上已经释放的四个字节进行操作赋值,没意义;
    32     rs = 11;
    33     
    34     demo();  // d = 0; 每次调用都会被重建;
    35     func();  // s = 11;
    36     
    37     printf("
    ");
    38     printf("main: rd = %d
    ", rd);  // rd = 13209588;
    39     printf("main: rs = %d
    ", rs);  // rs = 11;
    40     printf("
    ");
    41     
    42     return 0;
    43 }

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

       

    11,小结:

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

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

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

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

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

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

    此文为作者学习唐佐林老师的学习笔记,仅为交流共享之用,由此带来的后果,与作者无关;转载请注明转载出处;难免有错,欢迎指正,联系方式qunchao24@sina.com。
  • 相关阅读:
    CodeForce20C
    2019年9月末周java面试题总结
    java复习--框架部分
    java复习--Oracle数据库
    java复习--Web部分
    java复习--基础部分
    springboot中使用poi导入excel文件
    springboot中使用poi导出excel文件
    20.java自定义注解
    Redis入门
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10902803.html
Copyright © 2011-2022 走看看