1.形参和实参
实参是形参的初始值,实参类型必须与形参类型匹配。
函数形参列表可以为空。
void fact(int i) { };
fact(3.14); // 正确的,因为实参3.14可以隐式转换成int类型。
2.参数传递
当形参是引用时,形参将绑定到对应实参上,那么实参是引用传递(传引用调用);
当实参是值被拷贝给形参,形参和实参是两个互相独立的对象,那么实参是值传递(传值调用)。
使用引用形参,可以避免拷贝。当形参是大的类型对象或者容器对象,拷贝的效率低下,而引用可以避免拷贝,提升效率。
3.局部静态对象
static int i; //在函数内是局部静态对象
局部静态对象在第一次对象定义时初始化,直程序结束才销毁,即使它所在的函数执行结束也不会对它有影响。
4.const形参和实参
- 当形参是顶层const时,实参初始化形参时会忽略顶层const,也就是说传给顶层const形参常量对象或者非常量对象都是行的。
void count(const int a, int b);
int i = 1;
const int j = 2;
count(i, i); //正确的,i是非常量
count(j, i); //正确的,j是常量
- 尽量使用常量引用形参
普通引用作形参:
- 不用作参数传递(实参赋值给形参),节省开销,提高效率;
- 函数可以改变形参的值;
- 实参不能是const对象、字面值、或者类型转换的对象。
常引用作形参有3个作用:
- 不用作参数传递(实参赋值给形参),节省开销,提高效率;
- 函数不能改变形参的值;
- 实参可以是const对象、字面值、或者类型转换的对象。
void str(const string &s);
void str1(string $s);
const string s = "dsjaf";
str(s); // 正确
str1(s); // 错误
str("Hello World"); //正确
str1("Hello World"); //错误
5.数组形参
数组有两个性质:不允许拷贝数组,使用数组时会将其转换成指针;故当数组作为形参时,不能采用值传递。当给函数传递一个数组时,其实传递的是指向数组首元素的指针。
//print1等价于print2
void print1(const int*);
void print2(const int[]);
int i=0, j[2] = {0, 1};
print1(&1);
print1(j); // 正确,j会转换成指向j[0]的int*
当函数不需要对数组的元素写操作时,应该使用const;
void print(const int a[]); // 不能改变实参数组的元素
void print(int a[]); //可以改变实参数组的元素
6.return
return ; //只用于void类型函数中
return expression; //返回相应的类型
返回一个值的方式和初始化一个变量或形参的方式完全一样:返回的值用于初始化调用点的临时量,该临时量是函数调用的结果。
string make_plural(size_t cur, const string &word, const string &ending) {
return (ctr>1) ? word + ending : word;
}
// 该函数返回类型是string ,意味着返回值将被拷贝到调用点。因此,该函数返回一个word的副本或者一个未命名的string临时对象(其值是word + ending);
所以,当需要使用函数得到某个值时,使用指针会比直接返回值效率更高,少去了拷贝的过程,如下:
string make_plural(size_t cur, const string &word, const string &ending) {
return (ctr>1) ? word + ending : word;
}
string s;
void make_plural_ptr(size_t cur, const string &word, const string &ending, string *str) {
*str = (ctr>1) ? word + ending : word;
}
// 如下s和s1的值是一样的,但是使用s这种方法效率更高。
make_plural_ptr(cur,word,ending,&s);
string s1 = (cur,word,ending);