基本语法
引用的作用就是就是给变量起一个别名,基本语法如下:
数据类型 &别名 = 原名
实例:
int a = 20;
int &b = a;
cout << "a = " << a << endl; //20
cout << "b = " << b << endl; //20
这段代码中的两条输出语句的结果都是20,变量名a和b操控同一块内存空间。
引用注意事项
-引用必须初始化
-引用初始化后,不可以改变(也就是说引用在做了a的别名之后,就不可以在做其他变量的别名了)。
int a = 10;
//1.引用必须初始化
//int &b; 错误,必须要初始化
int &b = a;
//2.引用初始化之后,不可以改变
int c = 20;
b = c;//这句不是改变了引用的值,而是把c的值赋给了b,而b是a的别名,也就是说这时a、b、c全部是20
cout << "a = " << a << endl;//20
cout << "b = " << b << endl;//20
cout << "c = " << c << endl;//20
引用做函数的返回值
引用是可以作为函数的返回值存在的,但是不能是局部变量的返回值,因为局部变量在所代码在执行完之后,内存空间会被释放,返回其引用没有意义。但是可以返回静态局部变量的引用。静态局部变量在内存四区的全局区,只有当程序完全结束的时候内存空间才会被释放。
int& test01()
{
static int a = 100; //静态局部变量,存放在全局区
return a;
}
int main(void)
{
int &ref = test01();
cout <<"ref = "<< ref <<endl; //100
retuen 0;
}
由于可以返回引用,所以就有了另一个神奇的现象,函数调用可以作为赋值运算符的左值:
int& test02()
{
static int a = 100; //静态局部变量,存放在全局区
return a;
}
int main(void)
{
int &ref = test02();
cout <<"ref = "<< ref <<endl; //100
test02() = 1000;
cout <<"ref = "<< ref <<endl; //1000
retuen 0;
}
这段代码第一次打印输出为ref = 100,这是在意料之中的,但是第二次打印输出变成了1000。这看起来有些奇怪,我们来分析一下:
由于返回的是一个静态局部变量a的引用,而用一个引用变量ref来接收返回值,本质上是给a起了一个别名ref,而test02() = 1000这条语句本质上是给a的值修改为1000。所以再次输出ref的值,也就是a的值,当然也是1000了。
引用的本质
引用的本质实际上是一个指针常量,也就是用const修饰的指针名。被const修饰的指针的指向是不可以修改的,而指针指向的值是可以修改的。这也就解释了为什么引用一旦初始化之后就不可以更改。
int a = 10;
int& ref = a; //编译器自动转换为 int* const ref = &a;
ref = 20 //编译器发现是引用类型,自动转换为 *ref = 20;
C++是推荐我们使用引用技术的,语法很方便,所有的与指针的相关的操作都由编译器做好了。
常量引用
常量引用可以用来修饰形参,防止误操作。首先先来说明一下直接给引用赋一个初始是不可以的,但是在前面加上一个const就可以了。之所以出现这样的情况,是因为加上const之后,编译器把代码做了一些修改。
int a = 10;
int &ref = 10;//这样的操作是不被允许的,引用必须指向一块合法的内存空间。
const int &ref = 10;//正确操作 内部把代码改成了int temp = 10;const int &ref = temp;
ref = 20;//错误操作,加上const之后变为只读,不可以修改。
上面只是介绍一下原理,下面来看一下具体使用场景:修饰形参,防止误操作。
void showValue(const int &val)
{
//由于形参加入了const 从而在此函数体内部不可以修改val的值
cout << " v = " << v<< endl;
}
int main(void)
{
int a = 100;
showValue(a);
return 0;
}
