引用参数
概念
其本质是一个变量的别名,如果对一个变量声明了引用变量,那么该引用变量只能是该变量的别名,任何针对引用变量的操作都会被应用到原变量上。
因为其本质是一个变量的别名,所以声明的时候只能对将变量赋值给引用变量,并且引用变量在声明的时候必须初始化
,例如:
int a;
int & ref = a;
a = 10;
printf("a = %d\n", a);
ref++;
printf("ref = %d\n", ref);
在初始化引用变量之后,该引用变量便与用于初始化的变量绑定了,如果后续尝试将另一个变量赋值给该引用变量,则只会把另一个变量的值赋值给该引用变量,而不会将引用变量变成另一个变量的别名。例如:
int a, b;
int & ref = a;
a = 10, b = 20;
printf("a = %d\n", a);
ref = b;
printf("ref = %d\n", ref);
printf("a = %d", a);
与指针的区别
引用参数的概念与指针有些类似,但是它们之间还是有区别:
- 引用函数初始化之后便只跟一个变量绑定,后续不能转而绑定另一个变量,而指针可以指向另一个变量。
- 在使用的时候,引用变量作为一个变量使用,其用法与普通变量完全一致,而指针要用
*
来取指针中的值。
使用const
来节省形参复制开支
作为函数调用时的形参是引用变量最常用的用法,其优点是可以节省函数调用时复制变量的时间,但是为了防止发生异常,如果不需要改变引用变量的值,最好将变量修饰成const
。例如:
int sum(const int & a, const int & b);
使用引用参数的函数调用方式
由于引用变量是一个参数的别名,所以如果一个函数的形参使用了引用变量,那么在调用函数的时候必须通过一个变量将值传入函数,而不能传入直接数。例如:
int sum(int & a, int & b);
c = sum(10, 20); //错误,不能传入直接数
int a = 10, b = 20;
c = sum(a, b); //正确,必须通过变量将值传入函数
但是如果函数在声明的时候用const
修饰了引用变量,就可以传入直接数,编译器会创建一个临时的无名变量跟引用变量绑定。例如:
int sum(const int & a,const int & b);
c = sum(10, 20); //正确,引用变量被const修饰
这其中的原因很好理解,因为如果不用const
进行修饰,那么就表示函数可能会对引用进行修改,这是如果传入一个不可修改的立即数,就会引起程序执行错误。因为函数可能会对引用变量进行修改,如果这时创建一个临时变量,该变量将会在函数退出的时候被销毁,那么对该变量执行过的修改会变得毫无意义。
返回引用参数
在将一个引用参数作为返回值时,跟形参类似,传递的是一个别名,其本质是将一个变量的引用传递了出去。例如:
int & sum(int & a, int & b){
a = a + b;
return a;
}
int a= 10, b = 20;
int & c = sum(a, b);
printf("c = %d\n", c);
c += 10;
printf("a = %d\n", a);
这里sum()
返回的是变量a
的引用,所以对引用变量c
的改变也会影响到a
。
注意在返回一个引用变量的时候不能返回一个本地变量的引用,因为本地变量将会在函数执行完毕的时候销毁,之后传递出的引用将会失去引用的对象。例如:
int & sum(int & a, int & b){
int c = a + b;
return c; //错误,返回一个本地变量的引用
}
常用的做法是返回一个new
创建的变量,但是容易造成内存泄漏
,需要注意。例如:
int & sum(int & a, int & b){
int * c = new int;
* c = a + b;
return * c;
}