概念:
引用(类型名& +引用变量名):给已存变量取一个别名,和原变量使用的同一内存空间(类似不带*的指针)
void Func()
{
int flag = 1;
int& ra = flag;
cout << flag << endl << ra;
}
注意事项:
1)引用类型必须和引用实体类型一致 例:(int& ra=flag)flag必须是整型,否则系统报错
2)定义时必须初始化 例:(int& ra)未初始化,系统报错
3)只能引用一个实体,不能更改
4)同一个变量可以有多个引用
5)一般情况下不能引用常量
使用案例:
1
void Swap(int& left, int& right)
{
int tmp = left;
left = right;
right = tmp;
}
不需要传地址就可交换两个数的值
2
int& Add(int left, int right)
{
int ret = left + right;
return ret;
}
int main()
{
int& result = Add(1, 2);
cout << result << endl; //输出结果为3(函数结束局部变量ret被释放,但&result指向的栈帧空间未被清理)
Add(3, 4); //result的内容被修改为7
}
这种引用方式作为函数返回值时(返回局部变量)是不应该出现的
输出3原因:Add函数调用结束后,ret释放,但是result引用ret(共用一个空间),所以&result的结果没变(仍然指向ret的地址),栈帧并没有清理,result=3
Add(3,4)后result被修改为7:继续使用Add函数,栈帧内容会被新数据覆盖,因此result的内容被修改
引用和指针的共性和不同点:
传值:效率较低(以值作为参数或者返回值类型,在传参和返回期间
传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率非常低)
传地址:效率高,可通过形参改变实参
传引用:效率高,可达到类似指针的效果
引用和指针在反汇编中底层代码完全相同—引用就是指针
void Swap(int* a, int* b) //通过指针交换a,b的值
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void Swap(int& a, int& b) //引用
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 1, b = 2;
Swap(&a, &b);
Swap(a, b);
return 0;
}
反汇编中的底层代码:
可以看到两个底层代码完全一样,因为引用是按照指针方式来实现的。
不同点:
1)空间大小不同(指针4字节,引用和实体一致)
2) 引用在定义时必须初始化,指针没有要求。 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型
实体。
3)有多级指针,但是没有多级引用
int&—>int* const 等价 (引用只能和一个实体结合,不能修改)相当于(指针指向不能修改)
const int&—>const int* const 等价