博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

引用

Posted on 2023-03-12 21:18  乔55  阅读(67)  评论(0编辑  收藏  举报

引用基本概念

// 基本概念
- 引用声明:为一个已经存在的对象起一个别名,且可起多个别名。引用一经声明不可变更
- 引用只有声明没有定义,且不分配内存,引用只是一种声明,声明其与实体的关系
- 引用ref的值就是其绑定对象的值,引用ref的地址&ref就是其绑定对象的地址
- 不能声明对引用的引用,因为引用本身不是一个实体:int& ref = ref2;
- 定义一个引用后,所有对引用的操作,实际上是对绑定对象的操作


// 引用本质 
- int& ref = a;  // 在CPP内部相当于:int* const p = &a;
- 只要对a进行引用,就相当于定义了一个指向a的const指针


// 左值
- ++i,--i是左值表达式


// 右值
- i++,i--是右值表达式

// 左值引用
- int& ref = a;
- int a = 10; int& lef = a * 10;  // 错误,左值引用不可绑定到右值上

// 右值引用
- 右值引用:希望用右值引用绑定到一些即将销毁的或者临时对象上
- int&& ref = 10;  // 会产生临时变量。临时变量被当成右值
- int a = 10; int&& ref = a;  // 错误,右值引用无法绑定到左值上
- int&& ref = a * 10;  // 正确,右值引用绑定到右值上
- 右值引用目的:
  - 提高程序运行效率:把拷贝对象变成移动对象来提高程序运行效率
  - 移动对象如何产生:移动构造函数、移动赋值运算符。都需要右值引用来触发:&&

// const引用
- 可以使用任意表达式初始化const引用,只要表达式能转换成引用的类型即可
  - const int& ref1 = a;
  - const int& ref2 = 5;
  - const int& ref3 = ref2*10;
- const既可绑定到右值,还可以绑定到左值
  - const int& ref = 10;
  - const int& lef = a * 10;

// 普通引用
- 可通过普通引用ref改变其绑定对象的值:int& ref =a;  ref=b;
- 将普通引用绑定到const对象非法,const对象不可被修改,普通引用却可修改其绑定对象
- const int a = 10; int& ref =a;  // 错误,普通引用绑定到const对象
- int& ref = 10;                  // 错误,普通引用绑定到字面值,即const对象



// std::move
- 功能:将一个左值转成右值:string str = "i love";  string def = std::move(str);

// 怎样引用 
int& ref = x;	              // ref是x的别名
int& ref[10] = ...;	          // err,不存在引用数组
int (&ref)[10] = arr;	      // 引用一个具有10个int元素的数组 
int* p = &a; int* & ref = p;  // 对指针的引用

// 引用作函数参数
1. 好处:没有复制实参的开销,提高程序执行效率



// 引用作函数返回值
1. (int,struct)类型的变量在return语句中,直接返回一个变量,要执行复制操作
2. (int*,struct*)指针类型的变量在return语句,只做了一个地址传递,也进行了复制,但效率还是很高
3. (int&,struct&)引用引开在return语句中,代表的就是变量本身,没有复制的开销
4. 引用作为函数返回值,则要求返回的变量本身的生命周期一定要大于函数,即不要返回局部变量的引用
5. 不要轻易返回堆空间变量的引用,除非已经有了对该堆空间内存回收的策略
- 只要返回的对象不受该函数的限制即可:Test& xxx_fun(...){return* this;}
- 不能将返回的栈变量作为其他引用的初始化,如:int& ref=fun(); // 错误
- 不能将返回的栈变量作为其他表达式的左传,如:fun()=x;        // 错误