1.定义
引用的定义格式:
类型& 引用变量名 = 已定义过的变量名;
如:
int n=0;
int& m=n;
引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。
2.特点
1.一个变量可被引用多次。这就相当于一个人可以有许多别名。
2.引用必须初始化,并且只能在初始化时引用一次,不能改变为引用其他的变量。
3.引用与const
3.1常引用可以引用普通变量
int a=1;
const int& b=a;
但是b的值不能修改,因为它具有const常属性,而a可以修改。
3.2普通引用不能引用常变量
const int a=1;
int& b=a;//错误
const修饰的a变量只读,而引用变量b是可读可写的,如果引用成功就将权限放大了,因此是不允许的。
3.3常引用可以引用常变量
const int a=1;
const int& b=a;
3.4不同类型的引用
double a=1.1;
int& b=a;
这里的b是不能够被修改(赋值)的,因为b看似引用的是a,实则是一块临时变量的内存。
a是double类型,b是int类型,a赋值给b时要生成一个临时变量,因此b引用的是一块带有常性的临时变量,所以不能赋值。
4.引用作为参数
如果形参为引用类型,则形参是实参的别名。
void Swap(int& a,int& b)
{
int temp=a;
a=b;
b=temp;
}
这里能成功交换两个变量的值。
也就是说引用是一种输入输出型参数,因此当不希望修改引用参数的值时,尽量使用常引用传参。
5.引用作为返回值
注意:引用作为返回值时,引用的变量不能是函数内的局部变量
//int& Add(int d1,int d2) 错误!ret是Add栈帧内的局部变量
int Add(int d1,int d2)
{
int ret = d1 + d2;
return ret;
}
当函数栈帧销毁时,ret的内存也被释放,如果是引用返回值,那么将返回一块不可访问的内存空间。
传值返回与传引用返回汇编代码对比
可见将a,b的值相加后存入寄存器eax中,再将eax的值存入[ebp-4]的内存中,最后将[ebp-4]的地址存入eax中,这里返回的是局部变量ret的地址。
接收时,将eax指向地址处的值赋给eax,使接收变量接收。
先将接收到的地址处的值取出,再做赋值运算。
而传值返回只是将值返回了而已,不再赘述。
因此,
1.不要返回一个临时变量的引用。
2.如果返回对象出了当前函数的作用域依旧存在,则最好使用引用返回,这样更高效。
6.引用和指针
引用在语法上是给变量起了别名,在编译器中其实和指针一样,都开辟了空间。
引用在使用上比指针更直观,更不容易出错。
引用和指针的区别与联系:
1.引用只能在定义时初始化一次,之后不能改变指向其他变量,指针的指向是可变的。
2.引用必须指向有效的变量,指针可以为空。
**3.**sizeof指针对象和引用对象的意义不一样。
sizeof引用得到的是所指向的变量的大小,而sizeof指针是对象地址的大小。
4.指针和引用自增和自减的意义不同。
指针自增时增加的是所指向类型的大小,而引用自增永远是数值上加一。
5.引用比指针更安全,指针比引用更灵活。