提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
本文主要讲述值传递、地址传递和引用作为函数参数的区别,特别介绍引用的定义及注意细节,希望对引用进一步加深理解。
一、引用是什么?
1.引用通俗理解就是给变量起一个别名,对引用的操作与对变量直接操作是一样的
2.引用的常用格式与指针的定义差不多,如下:
int &b = a;//引用,相当于指针b也指向那块内存
3.引用必须初始化,不初始化会报错
int &c;//非法引用,引用必须初始化
4.引用不能重复引用,初始化后不能改变,也就是给一个变量起了一个别名后,不能再拿这个别名去指向别的变量
#include<iostream>
using namespace std;
int main() {
int a = 10;
int &b = a;//引用,相当于b也指向那块内存
int c = 50;
//int &b = c;//非法引用,引用初始化后不能改变
b = c;//如果此时给b赋值,这时候a也会改变
cout << "引用后b为 " << b<<endl;
cout << "引用后a为 " << a<<endl;
cout << "引用后c为 " << c << endl;
system("pause");
return 0;
}
二、引用作为函数参数,与值传递和地址传递进行比较
这里拿最简单a与b两个值交换作为例子,程序如下图。由结果我们可以看出
1.值传递的函数swap1并不会改变实参,ab的交换只在swap里面进行,相当于main函数的a和b复制一遍传给了swap的形参ab.
2.地址传递的函数swap2会改变实参,由于给swap2传形参时候传入的是地址指针,指向的是a和b的内存空间,在swap2函数里面,两个使得a和b两个地址相互交换了,最后实参也会改变
3.使用引用作为函数参数,同样也会改变实参。他的结构是最简单了,与值传递唯一区别就是定义函数参数时候,变量用引用void swap3(int &a_3, int &b_3) 。就是给a和b起一个别名,用一个指针指向它,ab交换时候就是ab地址交换,本质是定义了一个指针常量int *const a_3=&a_3;
#include<iostream>
using namespace std;
//值传递
void swap1(int a,int b ) {
int temp = a;
a = b;
b = temp;
cout << "1形参a= " << a << endl;
cout << "1形参b= " << b << endl;
}
//地址传递
void swap2(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
cout <<"\t"<< "2形参a= " << *a << endl;
cout << "\t"<<"2形参b= " << *b << endl;
}
//引用作为函数的参数
void swap3(int &a_3, int &b_3) {//结构简单,除了参数这里,其他没什么区别。本质上是一个指针常量int *const a_3=&a_3;
int temp = a_3;
a_3 = b_3;
b_3 = temp;
}
int main() {
int a = 10;
int b = 20;
swap1(a, b);
cout << "1实参a= " << a << endl;//结论:值传递不改变实参
cout << "1实参b= " << b << endl;
swap2(&a, &b);//取地址
cout << "\t" << "2实参a= " << a << endl;//结论:地址传递改变实参
cout << "\t" << "2实参b= " << b << endl;
int a_3 = 10;
int b_3 = 20;
swap(a_3, b_3);
cout << "3实参a= " << a_3 << endl;//结论:引用做函数参数传递改变实参
cout << "3实参b= " << b_3<< endl;
system("pause");
return 0;
}
结果图:
三、引用进阶:引用作函数的返回值
引用作函数的返回值 ,函数可以作为左值来接收,func()的返回值就是引用a。如下程序所示,
1.定义一个引用ret来接收引用函数,int &ret = func();
2. func() = 2000;这时候函数可以作为左值
3. func()的返回值就是引用a,相当于a=2000,ret是a的别名,所以才有ret最后输出2000
#include<iostream>
using namespace std;
int& func() {
static int a = 10;//静态变量,这个放在全局区,寿命比较长
return a;//引用a作为函数的返回值
}
int main() {
int &ret = func();//定义一个引用ret来接收引用函数
cout << ret << endl;
cout << ret << endl;
func() = 2000;//函数可以作为左值来接收,func()的返回值就是引用a,相当于a=2000,ret是a的别名,所以才有ret
cout << ret << endl;
cout << ret << endl;
system("pause");
return 0;
}
常量引用
1.形参定义时加上const,能够有效地防止误操作,防止形参改变实参。
#include<iostream>
using namespace std;
void prin( const int&ref) {
//ref = 10;//这里就会提示错误,表示表达式是可修改的左值
cout << "ref= " << ref << endl;
}
int main() {
int a = 50;
prin(a);
cout << "a= " << a << endl;
system("pause");
return 0;
}
2.如果直接在main函数定义,注意,在C++中,常量引用必须初始化,并且只能引用与其类型兼容的对象或字面值。因此,我们可以将常量引用绑定到一个字面值,如整数常量10,但不能将其绑定到一个非常量的对象,例如一个普通的整数变量。
//int &ref = 10;//非法提示:非常量引用的初值必须为左值,引用的必须是一块完整的内存空间。
const int &ref = 10;//这是正确的,相当于编译器把int temp=10;int &ref=temp;这两步做了
总结
本文主要讲了引用的定义,通俗理解就是给变量起一个别名,定义一个指针常量指向原变量。要注意引用并不多不初始化或者一个引用指向多个变量。重点理解值传递、地址传递和引用作为函数参数。可以看出,当需要实参改变时,使用引用定义函数参数这种方式结构更加简单。