第六章-函数

来源:互联网 发布:des加密算法 c语言 编辑:程序博客网 时间:2024/05/17 08:58

函数

 

1 函数基础

  • 我们通过调用运算符来执行函数。调用运算符的形式是(),它作用于一个表达式,该表达式是函数或者指向函数的指针。调用函数表达式的类型就是函数的返回类型。
  • 尽管实参与形参存在对应关系,但是并没有规定实参的求值顺序。

1-1 局部对象

  • 形参和函数体内部定义的变量统称为局部变量。

1-2 函数声明

  • 如果一个函数永远也不会被我们用到,那么它可以只声明没有定义。

1-3 分离式编译

 

2 参数传递

2-1 传值参数

  • 指针形参的行为和其他非引用类型一样。当执行指针拷贝操作时,拷贝的是指针的值。拷贝之后,两个指针是不同的指针。

2-2 传引用参数

2-3 const形参和实参

2-4 数组形参

  • 在传递多维数组形参的时候,编译器会一如既往地忽略掉第一个维度,所以最好不要把它包括在形参列表内。

2-5 main:处理命令行选项

2-6 含有可变形参的函数

  • 为了编写能处理不同数量实参的函数,C++11新标准提供了两种主要的方法:如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型;如果实参的类型不同,可以编写一种特殊的函数,也就是所谓的可变参数模板。
  • 拷贝或赋值一个initializer_list对象不会拷贝列表中的元素;拷贝后,原始列表和副本共享元素。
  • initializer_list对象中的元素永远是常量值。
  • 省略符号形参对应的实参无需类型检查。

 

3 返回类型和return语句

3-1 无返回值函数

  • 一个返回类型是void的函数也能使用return expression这种形式,不过此时return语句的expression必须是另一个返回void的函数。

3-2 有返回值函数

  • 调用一个返回引用的函数得到左值,其他返回类型得到右值。

3-3 返回指针数组

  • 如果我们想定义一个返回数组指针的函数,则指针的维度必须要跟在函数名字之后。然而,函数的形参列表也跟在函数名字后,且形参列表应优先于数组的维度。
  • 尾置返回类型跟在形参列表后面并且以一个->符号开头。为了表示函数真正的返回类型跟在形参列表之后,我们在本应该出现返回类型的地方放置一个auto。
  • decltype并不负责把数组类型转换成对应指针,所以decltype针对数组来说返回的就是数组类型。

 

4 函数重载

  • 一个拥有顶层const的形参无法跟另一个没有顶层的const的形参区分开来。
  • 如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时const是底层的。
  • 当我们传递一个非常量对象或者指向非常量对象的指针时,编译器会优先选择非常量版本的函数。

4-1 重载与作用域

 

5 特殊用途语言特性

5-1 默认实参

  • 一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值。
  • 用作默认实参的名字在函数声明所在作用域内解析,而这些名字的求值过程发生在函数调用点。

5-2 内联函数和constexpr函数

  • constexpr函数需要遵循:函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句。
  • 和其他函数不一样,内联函数和constexpr函数可以在程序中多次定义。毕竟,编译器想要展开函数仅有函数声明是不够的,还需要定义。不过,对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须完全一致。基于这个原因,内联函数和constexpr函数通常定义在头文件中。

5-3 调试帮助

  • assert是一种预处理宏。所谓预处理宏其实是一个预处理变量,它的行为有点类似于内联函数。如我们所知,预处理名字由预处理器而非编译器管理。
  • assert的行为依赖一个NDEBUG的预处理变量的状态。如果定义了它,则assert什么也不做。默认状态下是没有定义NDEBUG的,此时assert执行检查。

 

6 函数匹配

  • 函数匹配的步骤:第一步:选定候选函数(具备两个特征:与被调用的函数同名;声明在调用点可见);第二步:选定可行函数(具备两个特征:形参数量与本次调用提供的实参数量相等;每个实参的类型与对应的形参类型相同,或者能转换成形参的类型);第三步:寻找最优匹配(如果有且仅有一个函数满足以下两个条件,则找到最优:该函数每个实参的匹配都不劣于其他可行函数需要的匹配;至少有一个实参的匹配优于其他可行函数提供的匹配)。
  • 如果在可行函数中选不出最优匹配,编译器会报告二义性调用错误。

6-1 实参类型转换

  • 为了确定最佳匹配,编译器将实参类型到形参类型的转换划分为几个等级,具体排序如下:
  • 精确匹配(包括:实参类型和形参类型相同;实参从数组类型或函数类型转换成对应指针类型;向实参添加或删除顶层const)
  • 通过const转换实现的匹配(底层const)
  • 通过类型提升实现的匹配(小整型提升到int或者更大的整型)
  • 通过算术转换或指针转换实现的匹配
  • 通过类类型转换实现的匹配

 

7 函数指针

  • 当我们把函数名作为一个值使用时,该函数会自动转换成指针,此时函数名前的&是可选的。
  • 此外,我们还能直接使用指向函数的指针来调用该函数,此时函数指针前的*也是可选的。
  • 在指向不同函数类型的指针间不存在转换规则。
  • 如果要返回指向函数的指针,我们必须把返回类型写成指针形式,编译器不会自动将函数返回类型当成对应的指针类型来处理。
  • 当我们用decltype作用于某个函数时,它返回函数类型而非指针类型。

 

0 0