c++中的引用
1、定义
引用就是给一个变量起别名,定义好之后,对引用和变量操作效果一样。
2、语法
数据类型 &别名 = 原名
举个例子
int main() {
int a = 10;
int &b = a; //给变量a起别名
//在这,& 读作引用。因此,声明可以读作 "b是一个初始化为 a的整型引用",
cout << "a = " << a << endl; // 10
cout << "b = " << b << endl; //10
b = 100; //对引用和变量操作效果一样 ,所以之后a=b=100
cout << "a = " << a << endl; //100
cout << "b = " << b << endl; //100
system("pause");
return 0;
}`
3、注意
不存在空引用。引用必须连接到一块合法的内存。
一旦引用被初始化为一个对象,就不能被指向到另一个对象。(指针可以在任何时候指向到另一个对象。)
引用必须在创建时被初始化。(指针可以在任何时间被初始化。)
在实际程序中,我们不仅仅是用引用给某个变量起个别名,主要还是在函数参数传递过程中,可以利用引用的技术让形参修饰实参
可以简化指针修改实参
4、引用做函数参数
作用:函数传参时,可以利用引用的技术让形参修饰实参
优点:可以简化指针修改实参
函数参数传递有两种情况值传递和地址传递。在值传递的时候形参的改变无法对实参产生影响,但是地址传递的时候形参的改变会对实参产生影响。
引用传递:
在引用传递的过程中,被调函数的形参作为局部变量在堆栈中开辟了内存空间,这时存放的是由主函数放进来的实际参数变量的地址,被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主函数中的实参,正因为如此被调函数对形参的任何操作都会影响主函数中的实参。即引用传递的时候形参的改变会对实参产生影响。
总结:
1、引用传递,在函数定义时候,在形参前面加上引用运算符 “&” ,在函数被调用的时候,参数传递的内容不是实参的值,而是实参的地址,即将实参的地址存放到编译器为形参分配的内存空间上,因此对形参的任何操作都会改变相应实参的值。
2、地址传递,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的 形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。
下面通过实际案例比较三种形式的不同
//1. 值传递
void mySwap01(int a, int b) {
int temp = a;
a = b;
b = temp;
}
//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 a = 10;
int b = 20;
mySwap01(a, b);
cout << "a:" << a << " b:" << b << endl;
mySwap02(&a, &b);
cout << "a:" << a << " b:" << b << endl;
mySwap03(a, b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0;
}
5、引用做函数的返回值
作用:引用是可以作为函数的返回值存在的
用法:函数返回值类型 &函数名(){
函数体}
注意:1、不要返回局部变量引用,因为局部变量在函数结束后就被销毁了,此时的函数不知所措。
2、使用时,函数前要加上 &符号。
用法:函数调用作为左值
举个例子示例:
mySwap03(a, b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0; }
//返回局部变量引用
int& test01() {
int a = 10; //局部变量
return a; }
//返回静态变量引用
int& test02() {
static int a = 20;
return a; }
int main() {
//不能返回局部变量的引用
int& ref = test01();
cout << "ref = " << ref << endl;
cout << "ref = " << ref << endl;
//相当于是返回的变量a=1000,ref2是a的别名
ref存放的是a的地址
6、常量引用
6.1常引用声明方式:const 类型标识符 &引用名=目标变量名;
作用:用来修饰形参,防止误操作。
举例
//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {
//v += 10;
cout << v << endl;
}
int main() {
//int& ref = 10; 引用本身需要一个合法的内存空间,因此这行错误
//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
const int& ref = 10;
//ref = 100; //加入const后不可以修改变量
cout << ref << endl;
//函数中利用常量引用防止误操作修改实参
int a = 10;
showValue(a);
system("pause");
return 0;
}
注意:什么时候需要使用“常量引用”?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常量引用。
7、介绍引用的本质
之前介绍了引用的一些知识,接着说下引用的本质是什么。
本质:引用的本质在c++内部实现是一个指针常量.
(指针常量:指针指向是不可以修改的,指针指向的值是可以改动的)
结论: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;
// 注意:我们在实际使用的过程中,不要考虑太多,直接默认 ref = a 即可。
cout << "a:" << a << endl;
cout << "ref:" << ref << endl;
func(a);
return 0
未完待续~~~~~~~~~~