1. 引用变量
引用是已定义变量的别名,若使用int & x = a;
,即将x作为a的引用,其中的&不是地址运算符,而是类型标识符的一部分。事实上,x与a指向的是同一块内存空间,对x进行操作即对a进行操作。必须在声明引用变量时进行初始化。
/*
** 该程序试图通过指针改变引用变量x的指向
** 体现了引用与指针的区别
*/
int a = 100;
int *p = &a; //指针p指向a
int & x = *p; //x作为*p的引用,即对a的引用
int b = 50;
p = &b; //将指针p指向b,试图修改x为b的引用(invalid)
cout << "x = " << x << endl;
该程序最终输出为x = 100
。
可见,一旦将x初始化为*p,也就是使x指向a,再接下来即使将指针p指向b,也不能改变x已经是a的引用的事实。
2.引用在函数中的易错点
//error
const string & func(string & s1, const string & s2) {
string temp;
temp = s2 + s1 + s2;
return temp;
}
该程序存在一个致命缺陷,就是返回了一个指向函数func中声明的变量的引用。因为在函数结束后会释放函数中申请的内存空间,而返回值却指向了某块已经被释放的内存,会造成程序出错。
应修改为:
//right
string func(string & s1, const string & s2) {
string temp;
temp = s2 + s1 + s2;
return temp;
}
3.何时使用引用参数
1)使用引用参数的原因:
a.修改调用函数中的数据
b.通过传递引用而不是整个数据对象,以提高程序的运行效率
2)如何选择:
a.如果数据对象是数组,则只能使用指针;
b.如果数据对象是结构,则使用引用或指针;
c.如果数据对象是类,则使用引用;
d.如果数据对象很小,如内置类型或小型结构,则使用按值传递......
4.默认参数
默认参数是指当函数调用中省略了实参时,自动使用的一个值。
使用方式:
int func(const char * str, int n = 1);
在调用函数时,若使用 func(str, 5)
,则是正常的函数调用,将func函数中的n赋值为5;若是在调用函数时使用func(str)
,则会将n初始化为1,即在函数func中,n的值将为1,即使在函数中不对n进行赋值操作。
值得注意的是,在给参数列表添加默认值时,必须给所添加参数的右侧所有的参数都添加默认值。
int f(int a, int b = 1, int c = 2); //valid
int f(int a, int b = 1, int c); //invalid
int f(int a = 3, int b = 1, int c = 2); //valid
在调用函数时,实参必须按从左到右的顺序一次赋值给相应的形参,不能跳过任何参数。
下面几种调用方式:
f(10, , 12); //invalid
f(10); //valid
f(10, 11); //valid
默认值必须通过函数原型设置:
#include <iostream>
using namespace std;
char * left(const char * str, int n = 1); //在该位置设置默认值
int main() {
char str[10];
cout << "Enter a string : \n";
cin.get(str, 10);
char *a = left(str, 4); //传参 n = 4
cout << a << endl;
delete [] a; //释放之前的数组
a = left(str); //不传参,使用默认参数 n = 1
cout << a << endl;
delete [] a;
return 0;
}
char * left(const char * str, int n) { //此处不可写为 int n = 1
if(n < 0)
n = 0;
char *p = new char[n+1];
int i;
for(i = 0 ; i < n && str[i]; i++)
p[i] = str[i];
while(i < n)
p[i++] = 0;
return p;
}