1. 默认实参
某些函数有这样一种形参,在函数的很多次调用中它们都被赋予一个相同的值,此时,我们把这个反复出现的值称为函数的默认实参(default argument)。调用含有默认实参的函数时,可以包含该实参,也可以省略该实参。
比如,下面的代码:
typedef string::size_type sz;
string screen (sz ht = 24, Sz wid = 80, char backgrnd = ' ');
这里需要注意的有:
我们可以为一个或多个形参定义默认值,不过需要注意的是,一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值。
函数调用时实参按其位置解析,默认实参负责填补函数调用缺少的尾部实参(靠右侧位置)。例如,要想覆盖backgrnd的默认值,必须为ht和wid提供实参:
以下的调用方式就是错误的:
window = screen (, , '?');//错误:只能省略尾部的实参
因此,当我们设计含有默认实参的函数时,其中一项任务是合理设置形参的顺序,尽量让不怎么使用默认值的形参出现在前面,而让那些经常使用默认值的形参出现在后面。
有一点需要注意,在给定的作用域中一个形参只能被赋予一次默认实参。换句话说,,函数的后续声明只能为之前那些没有默认值的形参添加默认实参,而且该形参右侧的所有形参必须都有默认值。假如给定
//表示高度和宽度的形参没有默认值
string screen (Sz, Sz, char =' ');
我们不能修改一个已经存在的默认值:
string screen (Sz, Sz, char = '*');//错误:重复声明
但是可以按照如下形式添加默认实参:
string screen (Sz = 24, Sz = 80, char);// 正确:添加默认实参
默认实参初始值局部变量不能作为默认实参。除此之外,只要表达式的类型能转换成形参所需的类型,该表达式就能作为默认实参:
2.内联函数****和constexpr函数
规模较小的操作定义成函数有很多好处,主要包括:
- 阅读和理解shorterString函数的调用要比读懂等价的条件表达式容易得多。
- 使用函数可以确保行为的统一,每次相关操作都能保证按照同样的方式进行。如果我们需要修改计算过程,显然修改函数要比先找到等价表达式所有出现的地方再逐一修改更容易。
- ·函数可以被其他应用重复利用,省去了程序员重新编写的代价.
例如,如下代码:
//挑出两个string对象中较短的那个,返回其引用
const string &shorterstring (const string &sl, const string &s2)
{
return sl.size () <= s2.size () ? s1 : s2;
}
内联函数可避免函数调用的开销将函数指定为内联函数(inline),通常就是将它在每个调用点上“内联地”展开。假设我们把shorterString函数定义成内联函数,则如下调用:
cout << shorterString (Sl, s2) << endl;
将在编译过程中展开成类似于下面的形式
cout << (sl.size() < s2.size () ? sl : s2) << endl;
从而消除了shorterString函数的运行时开销。
在shorterString函数的返回类型前面加上关键字inline,这样就可以将它声明成内联函数了:
//内联版本:寻找两个string对象中较短的那个
inline const string &shorterstring (const string &sl, const string &s2)
{
return sl.size () <= s2.size () ? sl : s2;
}
一般来说,内联机制用于优化规模较小、流程直接、频繁调用的函数。
constexpr 函数