在函数的很多次调用中它们都被赋予一个相同的值,此时我们把这个反复出现的值称为函数的默认实参。
调用含有默认实参的函数时,可以包含该实参,也可以省略该实参。
我们可以为一个或多个形参定义默认值,不过需要注意的时,一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值。
如果想使用默认实参,只要在调用函数的时候省略该实参就可以。
函数调用时,实参按其位置解析,默认实参负责填补函数调用缺少的尾部实参(靠右侧)
当设计含有默认实参的函数时,其中一项任务是合理设置形参的顺序,让不怎么使用默认值的形参出现在前面。
对于函数的声明,通常习惯将其放在头文件中,并且一个函数只声明一次。但多次声明同一个函数也是合法的。
在给定的作用域中一个形参只能被赋予一次默认实参。
函数的后续声明只能为之前那些没有默认值的形参添加默认实参,而且该形参右侧的所有形参必须都有默认值。
通常应该在函数声明中指定默认实参,并将该声明放在合适的头文件中。
局部变量不能作为默认实参。此外只要表达式的类型能转换成形参所需的类型,该表达式就能作为默认实参。
用作默认实参的名字在函数声明所在的作用域内解析,而这些名字的求值过程发生在函数调用时:
但调用函数一般比求等价表达式的值要慢一些。
将函数指定为内联函数,通常就是将它在每个调用点上“内联地”展开。假设我们把 shorterString 函数定义成内联函数:
cout << shorterString(s1,s2) << endl;
// 将在编译过程中展开成类似于下面的形式
cout << (s1.size() < s2.size() ? s1: s2 ) << endl;
从而消除了 shorterString 函数的运行时开锁
在 shorterString 函数的返回类型前面加上关键字 inline ,就可以将它声明成内联函数。
constexpr 函数是指能用于常量表达式的函数。
定义 constexpr 函数的方法与其它函数类似,不过要遵循几条约定:函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条 return 语句。
constexpr 函数中可以有空语句、类型别名、using声明等。
内联函数和 constexpr函数通常定义在头文件中。
C++中有时会用到一种类似头文件保护的技术,以便有选择地执行调试代码。
程序可以包含一些用于调试的代码,但这些代码只在开发程序时使用。当应用程序编写完成准备发布时会屏蔽掉调试代码。
用到的两项处理功能 assert 、NDEBUG
assert 是一种预处理宏,也就是一个预处理变量,它的行为有点类似于内联函数。assert宏 使用一个表达式作为它的条件。
首先对 expr 求值,如果表达式为假,assert 输出信息并终止程序的执行。如果表达式为真,assert 什么也不做。
assert宏定在 cassert 头文件中。其常用于检查“不能发生”的条件。
assert 的行为依赖于一个名为 NDEBUG 的预处理变量的状态。如果定义了 NDEBUG 则 assert 什么也不做。默认状态下并没有定义 NDEBUG 所以assert 将执行运行时检查。
可以使用一个 #define 语句定义 NDEBUG ,从而关闭调试状态。
除了用于 assert 外,也可以使用 NDEBUG 编写自己的条件调试代码。如果 NDEBUG 未定义,将执行 #ifnder 和 #endif 之间的代码,如果定义了 NDEBUG 这些代码将被忽略。
变量_ _func_ _用于输出当前调试的函数的名字,是一个 const char 的一个静态数组,用于存放函数的名字。
可以使用这些常量在错误消息中提供更多信息。