默认实参
默认形参声明
在给定的作用域中,一个形参只能被赋予一次默认实参,这意味着在函数的多个声明中,只能为之前那些没有默认值的形参添加默认参数,而且该形参右侧的所有形参必须都有默认值。
默认形参初始值
局部变量不可以作默认实参,除此之外只要表达式的类型能转换成形参需要的类型,该表达式就可以作默认实参。
int w = 80;
char def = ' ';
void test(int a = w, char c= def)
{
cout << a << endl;
cout << c << endl;
}
int main()
{
int w = 100; //隐藏了外层定义的w,但是没有改变默认值
def = '*'; //会改变默认实参的值
test();
return 0;
}
内联函数和 constexpr 函数
调用函数比一般求等价表达式的值要慢一些,一次函数调用包含着一系列的工作:调用前要保存寄存器,并在返回时恢复;可能需要拷贝实参;程序转向新的位置执行。
内联函数可以避免函数调用的开销,通常就是将它在每个调用点上“内联的”展开。
inline const string &shorterString(const string &str1, const string &str2)
{
return str1.size() <= str2.size() ? str1 : str2;
}
调用时:
cout<<shorterString(s1,s2)<<endl;
在编译的过程中展开成类似下面的形式:
cout<<str1.size() <= str2.size() ? str1 : str2<<endl;
注意:
- 内联声明只是想编译器发出一个请求,编译器可以选择忽略这个请求。
- 内联机制一般用于优化规模较小、流程直接、频繁调用的函数。
- 很多编译器不支持内联递归函数。
constexpr
constexpr
函数是指用于常量表达式的函数。
定义 constexpr
函数:
- 函数的返回类型以及所有的形参类型都得是字面值类型。
- 函数体内有且只有一条return 语句。
constexpr int new_sz(){ return 42;}
int main()
{
constexpr int foo = new_sz();
return 0;
}
new_sz
没有参数,编译器在程序编译时会验证 new_sz
函数返回的是不是常量表达式,所以可以使用 new_sz
函数初始化 constexpr
类型的变量。
执行该初始化任务时,编译器把对 constexpr
函数的调用结果替换成其结果值,为了能够在编译过程中随时展开, constexpr
函数被隐式地指定为内联函数。
注意:
constexpr
函数返回的不一定是常量表达式:
constexpr size_t scale(size_t cnt) {return new_sz() * cnt};
如果scale
的实参是常量表达式,那么它的返回值也是常量表达式,反之则不然:
int arr[scale(2)]; //正确,scale(2)是常量表达式
int i = 2; // i 不是常量
int a2[sclae(i)]; //错误,scale(i)不是常量表达式
constexpr
函数体内也可以包含其他语句,只要这些语句不执行任何操作就行,例如:空语句,类型别名,using
声明。
调试帮助
assert 预处理宏
assert
是一种预处理宏,所谓的预处理宏其实就是一个预处理变量,它的行为类型于内联函数,assert
宏使用一个表达式作为条件:
assert(expr);
- 首先会对
expr
求值,如果表达式为假,assert
输出信息并终止程序的执行,如果表达式为真,assert
什么也不做。 assert
宏定义在cassert
头文件中,预处理器的名字由预处理器而非编译器管理。- 和预处理变量一样,宏名字在程序中必须唯一,含有
cassert
头文件的程序不能再定义名为assert
的变量、函数或者其它实体。 assert
宏通常是用来检查不能发生的条件。assert
宏可以作为一种调试程序的辅助手段,但是不能用它替代真正的运行时逻辑检查,也不能替代程序本身应该包含的错误检查。
NDEBUG预处理变量
assert
的行为依赖于一个名为 NDEBUG
的预处理变量的状态,如果定义了 NDEBUG
,则 assert
什么也不做。默认情况是没有定义 NDEBUG
。
C++ 预处理中定义的对于程序调试很有用的名字:
__func__
:存放当前调试函数的名字。__FILE__
:存放当前文件名的字符串字面值。__LINE__
:存放当前行号的整型字面值。__TIME__
:存放文件编译时间的字符串字面值。__DATE__
:存放文件编译日期的字符串字面值。