套个盾:这只是我自己的学习笔记,有错的地方欢迎大家斧正
1.基本作用:给变量取别名
语法:数据类型 &别名=原名;
2.注意事项:引用必须初始化,且初始化后不可更改
3.引用做函数参数
作用:避免使用指针修改实参
#include <iostream>
using namespace std;
//交换函数
//1.值传递
void myswap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "swap01 x=" << a << endl;
cout << "swap01 y=" << b << endl;
}
//2.地址传递
void myswap02(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//3.引用传递
void myswap03(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int x = 100;
int y = 256;
/*
myswap01(x, y);
printf("x=%d\r\n", x);
printf("y=%d", y);
//此时主函数的printf打印结果中x、y的值
//没有改变,因为值传递形参不会修饰实参
*/
/*
myswap02(&x, &y);
printf("x=%d\r\n", x);
printf("y=%d", y);
//地址传递,此时形参可以修饰实参
*/
myswap03(x, y);
printf("x=%d\r\n", x);
printf("y=%d", y);
//引用传递,形参也会修饰实参
system("pause");
return 0;
}
4.引用做函数的返回值
作用:引用也可以用做函数的返回值
注意事项:不要返回局部变量引用
用法:将函数调用作为左值
我们在声明一个函数时首先要做的就是声明一个函数的返回值类型,比如void、int等等,当然这个返回值在C++中也可以是一个引用。
看这样的一段代码
#include <iostream>
using namespace std;
//引用做函数的返回值
//attention:
//1、不要返回局部变量的引用
int& test01()
{
int a = 10;//局部变量存放在内存四区中的栈区,执行结束后占用的内存就被释放
return a;
}
//2、函数的调用在C++中可以作为左值存在
int main()
{
int& ref=test01();
cout << "ref=" << ref;
system("pause");
return 0;
}
运行结果:
只有第一次运行结果才是10,因为编译器帮我们对栈中的数据做了一次保留。
如果一个函数的返回值是调用,那么它就可以作为赋值时的左值。话不多说,上代码。
#include <iostream>
using namespace std;
//引用做函数的返回值
//attention:
//1、不要返回局部变量的引用
int& test01()
{
int a = 10;//局部变量存放在内存四区中的栈区,执行结束后占用的内存就被释放
return a;
}
//2、函数的调用在C++中可以作为左值存在
int& test02()
{
static int a = 10;//声明a为静态变量,存放在全局区,程序执行结束后由系统释放
return a;
}
int main()
{
//int& ref=test01();
//cout << "ref=" << ref<<endl;
int& ref=test02();
cout << "ref=" << ref<<endl;
cout << "ref=" << ref << endl;
test02() = 1000;//如果一个函数的返回值是引用,那么她就可以作为赋值的左值
cout << "ref=" << ref << endl;
cout << "ref=" << ref << endl;
system("pause");
return 0;
}
5.引用的本质
本质:内部实现的指针常量
先上代码:
#include <iostream>
using namespace std;
//发现是引用,转换为int * const ref=&a;
void func(int& ref)
{
ref = 100; //ref是引用,转换为*ref=100;
}
int main()
{
int a = 10;
int& ref = a;
//本质上等价于
//int* const ref = &a;
//指针常量的指针指向不可更改
ref = 20;
//等价于*ref=20;
cout << "a=" << a << endl;
cout << "ref=" << ref << endl;
func(a);
system("pause");
return 0;
}
“int a=10;”等价于我们开辟了一块内存为(假设)0x0011的内存空间用来存放一个名叫a的变量,它的值是10.
“int &ref=a;"相当于int *const ref=&a;这个指针被const修饰,指向为a的存储地址且指向内容不可更改,但我们可以依靠解引用的方式更改这个地址存放的内容。直接赋值ref=20。用起别名的说法也能圆回来,给a起了别名叫ref,然后给ref赋值为20。
输出结果:
6.常量引用
作用:修饰形参,防止误操作。在函数形参列表中,可以加const修饰形参,防止形参改变实参。
知识储备:
int a = 10;
int& ref = a;
这在C++中是一种被允许的操作,因为a作为一个普通的整形变量内存地址是可操作的。
int& ref = 10;
但这样就不行了,“10”并不是一个声明过的变量。不过我们可以利用const关键字实现这个操作。
/*但在加上const之后
编译器将代码修改为int temp=10;
const int &ref=temp;*/
const int& ref = 10;
//现在ref处于只读状态
下面开始正式介绍。
#include <iostream>
using namespace std;
//来给标准IO函数套个壳
void OLED_PrintValue(int& val)
{
printf("val=%d;\r\n", val);
}
int main()
{
//常量引用
//使用场景:修饰形参防止误操作
//int a = 10;
//int& ref = a;//a的内存空间可操作
/*int& ref = 10;
不被允许的操作
*/
/*但在加上const之后
编译器将代码修改为int temp=10;
const int &ref=temp;*/
//const int& ref = 10;
//现在ref处于只读状态
int x = 100;
OLED_PrintValue(x);
system("pause");
return 0;
}
这样子我们把x通过值传递打印了出来,但如果我们在打印函数中对形参进行了修饰呢?
#include <iostream>
using namespace std;
//来给标准IO函数套个壳
void OLED_PrintValue(int& val)
{
val = 99;
printf("val=%d;\r\n", val);
}
int main()
{
//常量引用
//使用场景:修饰形参防止误操作
//int a = 10;
//int& ref = a;//a的内存空间可操作
/*int& ref = 10;
不被允许的操作
*/
/*但在加上const之后
编译器将代码修改为int temp=10;
const int &ref=temp;*/
//const int& ref = 10;
//现在ref处于只读状态
int x = 100;
OLED_PrintValue(x);
printf("x=%d\r\n;", x);
system("pause");
return 0;
}
这个时候的运行结果是:
x作为实参因为引用的原因被形参修饰了,为了避免这个情况, 我们可以再函数体声明形参时加上const,如图所示,此时val成为了一个不可修改的左值。
/*引用部分完结撒花!*/