函数在调用的时候,实参需要和形参的类型一致或者能够转换。函数的形参的类型是必须的,但是名字是可选的(函数的原型并补包括参数的名字),用不到就可以不命名。

C++当中,名字有作用域,对象有生命周期。内层如果定义了和外层一样的名字,此时外层的名字会被隐藏。对于局部变量,作用域开始的时候创建,作用域结束就销毁。
对于局部的静态变量,函数第一次运行时初始化,程序结束才销毁。所以可以使用局部静态变量来统计一个函数在程序运行期间被调用的次数。
局部变量必须初始化,否则局部变量的值是未定义的,但是局部静态变量会执行静态初始化(例如int会被初始化为0)。
对于定义于所有函数体之外的变量,生命周期贯穿整个程序的运行期间,其实就是全局变量和全局静态变量,这些也是执行静态初始化,或者说是值初始化。

函数必须是先声明后使用。函数可以声明多次但是只能被定义一次(跟跨文件extern变量一样),这里要注意的是内联函数是可以被定义多次的,但是这些定义要一样。
函数的声明、接口、三要素包括返回类型、函数名、形参类型。这里有意思的是,在重载函数的时候,不能只通过返回类型不同来重载函数,因为在调用选择最佳匹配函数的时候并没有关于函数返回类型的考虑。
C++支持分离式编译。
实参初始化形参的过程和变量的初始化是一样的。
函数的参数传递分为值传递和引用传递,值传递就是调用拷贝构造函数,引用传递就是传递引用。
函数要操作外部对象,可以通过指针和引用达到。
因为数组不能赋值和拷贝的原则,所以形参的类型不能是数组,如果定义成数组也会转换成指向数组元素的指针。例如int a[10]作为函数形参实际上等价于inta.但是可以定义数组的引用。
当函数返回左值的时候,函数的调用结果是可以作为赋值号的左边的,例如返回左值引用。
形参类型为top-level const和没有这个const的同类型是一样的,所以函数 void fun(int i) 和void fun(const int i)会造成重复定义。
当函数的返回类型是数组或者函数指针的时候函数的声明会变得复杂,此时可以使用后置返回类型,例如 auto fun(int i) ->int;当然,也可以使用decltype
main函数的参数可以是int main(int argc ,char
argv[]),argv第一个元素是程序的名字,后面依次是命令行的参数。

函数的可变形参可以通过 initializer_list ,...省略符形参和可变参数模板三种方法实现。
第一张适用于参数类型相同,第二种是为了访问一些C代码,第三种是模板相关的知识,可以用于实参类型不同的情况。

函数返回一个值的初始化方式和初始化一个变量或形参的方式相同:返回的值用于初始化调用点的一个临时变量,该临时变量就是函数调用的结果。

C++标准规定,函数可以返回{}包围的初始化列表,用于对调用结果进行初始化,如果{}为空,则调用结果变量进行值初始化。

main函数不支持递归和重载,当函数内部不包含return语句的时候也能通过编译,控制流到达结尾没有return的话编译器会自动加上return 0的语句。
main函数返回0代表成功,为了让返回值与机器无关,可以使用定义在cstdlib中的EXIT_FAILURE和EXIT_SUCCESS变量。

应该避免区分不明显的函数重载,因为匹配过程很扯淡。函数在调用过程中,名字查找发生在类型检查之前。就是说,遇到调用语句,函数如果在当前作用域找到一样的函数名字,就会停止名字查找转而开始检查参数和类型,如果参数的数量或者类型不匹配就会报错,即使在外层作用域有符合调用要求的函数也会这样,外层的会被忽略,因为名字查找的时候都没机会进入候选队伍。
分析函数的调用过程中,不要忘记量默认实参可以提供多个候选。

在给定的作用域当中,一个形参只能在声明中被赋予一次默认实参。就是所,在所有的函数声明当中,不能存在两个声明同事对一个形参赋默认值。
当声明需要给某个参数赋默认实参的时候,这个形参右侧的形参应该已经在前面的声明中获得默认值,而且这些在前面已经获得默认实参的形参在这次声明当中值给出类型和名字就可以了。
在函数返回类型之前添加inline可以向编译器发出内联请求,但是编译器可以忽略,可以成功内联的函数一般不长。

对于带有参数的constexpr函数,如果调用的时候实参是字面值,那返回值就是constexpr,否则不是。

调试帮助:assert定义在cassert当中,用于断言表达式为真。为假的时候就会终止程序运行。这个预处理宏依赖于一个NDEBUG的预处理变量,可以通过#define或者命令行处理的时候指定。
如果NDEBUG定义量,assert就会失效。
编译器和预处理器预定义的变量(都是以两个下划线开头和结尾的):
func 函数的名字
FILE 代码文件名
TIME 文件编译时间
DATE 文件编译日期

当形参里面有const&和非const引用的时候,编译器会根据实参是否是const来确定最佳匹配,如果实参是const,那会优先匹配const的形参。
函数寻找最佳匹配的过程:
名字查找-锁定候选函数-与调用函数同名,在调用点可见。在一层作用域找到之后就会停止查找外一层的作用域。
类型和数量检查-从候选函数中锁定可行函数-形参数量相同、对应的类型也相同或者可以转换。默认实参可以提供多个可行函数。
最佳匹配-从可行函数中选择最佳匹配-形参与实参类型越接近越匹配。该函数每个实参的匹配都不劣于别的函数。该函数至少有一个实参的匹配优于别的函数。
走完没找到就会报错或者二义性调用。
精确匹配,记住最简单的,不需要类型转换的优于需要类型转换的。
但是应该避免这么玩,自己恶心自己呢。

声明一个函数指针,把函数名换成(指针名)就好。注意()必须有。把函数名当值用的时候会自动转换成指针,而且可以通过函数指针直接调用函数,当然,硬是要解引用也不是不行。
使用decltype作用于函数名的时候,得到的是函数类型而不是函数指针,需要加

如果把函数的返回类型定义为函数类型,那么返回类型并不会自动转化成指针。函数并不能返回一个函数类型,但是可以返回一个函数指针。
因为定义复杂,可以多使用decltype和尾置返回类型。

最后一点:函数是为了代码复用,减少重复代码。