引用的基本作用
引用作用:给变量起别名
数据类型&别名=原名
int a=10;
int &b=a;
b=20;
cout<<a<<endl; //20
//因为ab操作同一块内存
引用的注意事项
- 引用必须初始化
- 引用初始化后就不能在改变
int a=10;
//int &b; //err
int &b=a; //ok
//引用必须初始化
//引用初始化后就不能改变
int c=20;
b=c; 等号是赋值操作而不是更改引用
cout<<a<<b<<c<<endl; //都是20
引用做函数参数
- 作用:函数传参时,可以利用引用的技术让形参修饰实参
- 优点:可以简化指针修改 实参
交换函数
//1值传递
void myswap01(int a,int b)
{
int tmp=a;
a=b;
b=tmp;
} //主函数中调用后 形参改变了 实参ab并没有发生改变
//2地址传递
void myswap02(int *a,int *b)
{
int tmp=*a;
*a=*b;
*b=tmp
}//ok 形参会修饰实参
myswap02(&a,&b)
//3引用传递
void myswap03(int &a,int &b)
{
int tmp=a;
a=b;
b=tmp;
} //引用传递,形参会修饰形参
myswap03(a,b); 用别名操作修改,和原名一样的
//如果用指针还要解引用
引用做函数返回值:
/*
引用做函数返回值
1.不要返回局部变量的引用
2.函数的调用可以作为左值
*/
int & test01()
{
int a=10;//栈区;
return a;
}
int main()
{
int &ref=test01();
cout<<"ref="<<ref<<endl;//10,因为编译器做了保留
cout<<"ref="<<ref<<endl;//乱码,第二次结果错误,因为a的内存已经释放
}
//
//
//
//
//
//
int & test02()
{
static int a=10; //静态变量存放在全局区,上面的数据在程序结束后由系统释放
return a;
}
int main()
{
int &ref2=test02();
cout<<"ref2="<<ref2<<endl;
cout<<"ref2="<<ref2<<endl;
//如果函数的返回值是一个引用,这个函数调用可以作为左值
test02()=1000;//相当于a=1000; ref2本来就是a的别名
cout<<"ref2="<<ref2<<endl;
cout<<"ref2="<<ref2<<endl;
}
引用的本质
本质:引用的本质在c++内部实现是一个指针常量
//发现是引用,转换为int *const ref=&a;
void func(int &ref)//同一个引用来接收
{
ref=100;//ref是引用,转换为*ref=100;
}
int main()
{
int a=10;
//自动转换为int *const ref=&a;指针常量时指针指向不可改变,也说明为什莫指针引用不可以更改
int &ref=a;
ref=20;
//内部发现ref时引用 ,自动帮我们转换为*ref=20;
cout<<a<<endl;
cout<<ref<<endl;
func(a);
return 0;
}
结论:c++推荐使用引用技术,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了
常量引用
作用:常量引用主要是用来修饰形参,防止误操作
在函数形参列表中,可以加const修饰形参,防止形参改变实参
int main()
{
int a=10;
// 引用必须引用一块合法的内存空间
int &ref=a;//ok int &ref=10;//err
//加上const之后编译器将代码修改 int tmp=10; const int &ref=tmp;
const int &ref=10;//现在这个引用引的是一个临时的空间
ref=20;//err 加上const后变成只读不可修改
}
void showval(const int &val)
{
//val=1000;//不加const 时这样就会出现改动,,可能是误改,底下的a也会修改
//所以就要加上const;
cout<<"val="<<val<<endl;
}
int main()
{
int a=100;
showval(a);
}