引用
引用 不是新定义一个变量,而 是给已存在变量取了一个别名 ,编译器不会为引用变量开辟内存空
间,它和它引用的变量 共用同一块内存空间。
比如: 李逵 ,在家称为 " 铁牛 " ,江湖上人称 " 黑旋风 " 。
类型 & 引用变量名 ( 对象名 ) = 引用实体;
引用类型 必须和引用 实体 是 同种类型 的
void TestRef()
{int a = 10;int& ra = a;//<====定义引用类型printf("%p\n", &a);printf("%p\n", &ra);
}
引用特性
1. 引用在 定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{int a = 10;// int& ra; // 该条语句编译时会出错int& ra = a;int& rra = a;printf("%p %p %p\n", &a, &ra, &rra);
}
一个变量可以有多个引用,对同一块空间的多个外号命名
int main()
{ // int& b; // 引用在定义时必须初始化int a = 0;int& b = a;int& c = a;int& d = b;int x = 1;// 赋值b = x;return 0;
}
常引用
在引用的过程中
// 权限可以平移
// 权限可以缩小
// 权限不能放大
void TestConstRef()
{const int a = 10;//int& ra = a; // 该语句编译时会出错,a为常量const int& ra = a;// int& b = 10; // 该语句编译时会出错,b为常量const int& b = 10;double d = 12.34;//int& rd = d; // 该语句编译时会出错,类型不同const int& rd = d;
}
1.权限的放大
此类是权限的放大,a是不能修改的常量,给a取了别名b同样不能修改,但是取别名时只是给了名字b并没有强调不能修改权限,放大了权限,使用错误。
2.权限的平移
a能做的事c也能做,a不能做的c也不能做。
3.权限的缩小
在初始化x时没有强调权限,x可以随意更改,给x取了别名y,在取别名时强调y不能改变,此类是权限的缩小。(理解为x什么都可以干,y只能吃饭喝水,做事有限制)
4.赋值
赋值是产生一个临时变量,i的值给临时变量,临时变量是double类型,临时变量的值赋给d
临时变量具有常性,不能用其他别名
所以下面的形式错误,是一种权限的放大
正确形式
同理
第一个调用函数,用ret接收时,首先产生一个临时拷贝a的值,临时常量具有常性,再将临时拷贝的值给ret,ret接收值后无论怎么改变不会影响函数里的a
第二个调用函数,同理会产生一个拷贝,拷贝a的值,临时常量具有常性,不能用ret作为常量的别名。
更改为权限平移是正确的
使用场景
1. 做参数 形参的改变会影响实参
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
2. 做返回值
注意: 如果函数返回时,出了函数作用域, 如果返回对象还在( 还没还给系统 ) ,则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回。
这里以顺序表为例使用引用的便利
int& Add(int a, int b)
{int c = a + b;return c;
}
int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2) is :"<< ret <<endl;return 0;
}
ret作为c的别名接收函数的返回值,第一次传入参数接受结果为3,第二次传参结果为7,所以运行结果是7
传值、传引用效率比较
以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直
接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效
率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
引用和指针的区别
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用 在定义时 必须初始化 ,指针没有要求
3. 引用 在初始化时引用一个实体后,就 不能再引用其他实体 ,而指针可以在任何时候指向任何
一个同类型实体
4. 没有 NULL 引用 ,但有 NULL 指针
5. 在 sizeof 中含义不同 : 引用 结果为 引用类型的大小 ,但 指针 始终是 地址空间所占字节个数 (32
位平台下占 4 个字节 )
6. 引用自加即引用的实体增加 1 ,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同, 指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全