4 引用的本质

1 引用的意义

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

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

  • swap 函数的实现对比

    //指针方法
    void swap(int* a,int* b)
    {
        int t = *a;
        *a = *b;
        *b = t;
    }
    
    //引用方法
    void swap(int& a,int& b)
    {
        int t = a;
        a = b;
        b = t;
    }
    
  • 注意:函数中的引用形参不需要初始化,它的初始化发生在函数调用的时候

2 特殊的引用

  • const 引用

    • 在 C++ 中可以声明 const 引用

    • const Type& name = var;

    • conts 引用让变量拥有只读属性

      int a = 4;
      const int& b = a;
      int* p = (int*)&b;  //等价于对变量a取地址
      
      b = 5;  //error: assignment of read-only reference 'b'
      *p = 5;  //正确,修改变量a的值
      
  • 当使用常量const 引用进行初始化时,C++ 编译器会为常量值分配空间,并将引用名作为这段空间的别名

    const int& b = 1;
    
    int* p = (int*)&b;
    
    b = 5;  //error: assignment of read-only reference 'b'
    *p = 5;  //正确: 修改变量a的值
    
    • 使用常量对 const 引用初始化后将生成一个只读变量
  • 问题:引用有自己的存储空间么?

    • 有!

    • Demo

      #include <stdio.h>
      
      struct TRef
      {
          char& r;
      };
      
      int main(int argc, char *argv[])
      { 
          char c = 'c';
          char& rc = c;
          TRef ref = { c };
          
          printf("sizeof(char&) = %d
      ", sizeof(char&));  //1
          printf("sizeof(rc) = %d
      ", sizeof(rc));  //=> sizeof(c) = 1
          
          printf("sizeof(TRef) = %d
      ", sizeof(TRef));  //0?
          printf("sizeof(ref.r) = %d
      ", sizeof(ref.r));  //=> sizeof(c) = 1
      
          return 0;
      }
      
    • 运行结果

      sizeof(char&) = 1
      sizeof(rc) = 1
      sizeof(TRef) = 4
      sizeof(ref.f) = 1
      

3 引用的本质

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

    Tyep& name;
    void f(int& a)
    {
        a = 5;
    }
    
    //等价于
    Type* const name;
    void f(int* const a)
    {
        *a = 5;
    }
    
  • 注意

    • C++ 编译器在编译过程中用指针常量作为引用的内部实现,因此引用所占用的空间大小与指针相同
    • 从使用的角度,引用只是一个别名,C++ 为了实用性而隐藏了引用的存储空间这一细节
  • 引用的存储空间

    • Demo

      #include <stdio.h>
      
      struct TRef
      {
          char* before;
          char& ref;
          char* after;
      };
      
      int main(int argc, char* argv[])
      {
          char a = 'a';
          char& b = a;  //1)取变量a的地址 2)将a的地址赋值给b对应的4个字节的内存空间中去
          char c = 'c';
      
          TRef r = {&a, b, &c};
      
          printf("sizeof(r) = %d
      ", sizeof(r));
          printf("sizeof(r.before) = %d
      ", sizeof(r.before));
          printf("sizeof(r.after) = %d
      ", sizeof(r.after));
          printf("&r.before = %p
      ", &r.before);
          printf("&r.after = %p
      ", &r.after);
      
          return 0;
      }
      
    • 编译运行

      sizeof(r) = 12
      sizeof(r.before) = 4
      sizeof(r.after) = 4
      &r.before = 0xbf8a300c
      &r.after = 0xbf8a3014
      
  • 函数引用返回:返回局部变量的引用/指针可能会造成内存泄漏

    • Demo

      #include <stdio.h>
      
      int& demo()
      {
          int d = 0;
          
          printf("demo: d = %d
      ", d);
          
          return d;  //error: 返回局部变量的引用 <=> return &d
      }
      
      int& func()
      {
          static int s = 0;
          
          printf("func: s = %d
      ", s);
          
          return s;  //返回静态局部变量 => 正确,静态变量不会随着函数调用的返回而被摧毁
      }
      
      int main(int argc, char* argv[])
      {
          int& rd = demo();
          int& rs = func();
          
          printf("
      ");
          printf("main: rd = %d
      ", rd);
          printf("main: rs = %d
      ", rs);
          printf("
      ");
          
          rd = 10;
          rs = 11;
          
          demo();
          func();
          
          printf("
      ");
          printf("main: rd = %d
      ", rd);
          printf("main: rs = %d
      ", rs);
          printf("
      ");
          
          return 0;
      }
      
    • 编译

      test.cpp: In function ‘int& demo()’:
      test.cpp:5:9: warning: reference to local variable ‘d’ returned [-Wreturn-local-addr]
           int d = 0;
               ^
      
    • 运行

      demo: d = 0
      func: s = 0
      
      main: rd = 13209588  <=>rd 等价于一个野指针
      main: rs = 0
      
      demo: d = 0
      func: s = 11
      
      main: rd = 132095588
      main: rs = 11
      
原文地址:https://www.cnblogs.com/bky-hbq/p/13695492.html