第六章 函数 207

6-1函数基础
返回类型 函数名字( 形参列表)
{
函数体
}
空形参列表
void f( ){ //}//隐式地定义形参列表
void f(void){//}//显式地定义形参列表
函数声明时,可以忽略形参名,必须写上形参
1、局部对象
形参和函数体内部定义的变量统称为局部变量
自动对象:只存在于块执行期间的对象
局部静态对象:
在这里插入图片描述
ctr被定义为局部静态变量,第一次调用时值为1,第二次是2,以此类推,直到输出10
如果ctr不是静态变量,每次都只会输出1
2、函数声明
函数声明也称作函数原型,包括返回类型,函数名,形参列表
3、分离式编译
在一个文件中定义一个函数,在其他文件中声明并使用它
在这里插入图片描述
$是系统提示符,CC是编译器的名字,#后面是命令行下的注释语句
在fact.cc中定义了一个函数,在factMain.cc创建的main函数中调用这个函数
6-2形参传递
1、传值参数
函数对形参做的所有操作都不会影响实参的值
指针形参:
在这里插入图片描述
p指向i,p所指的对象改变,n的值不变
在这里插入图片描述
在这里插入图片描述
函数调用改变了i的值,i的地址是实参,i的地址不变
2、传引用参数
通过使用引用形参,可以改变实参的值在这里插入图片描述
在这里插入图片描述
j的值被修改成0
使用引用避免拷贝
拷贝大的类类型对象或者容器对象比较低效,有的类类型不支持拷贝,使用形参访问更明智
在这里插入图片描述
当函数无需修改引用对象的值时,最好使用常量引用
使用引用形参返回额外信息
一个函数只能返回一个值,使用引用形参可以实现返回多个值
统计一个字母在字符串中第一次出现的位置和它出现的次数,可以定义一个新的数据类型,也可以使用引用形参
在这里插入图片描述
在这里插入图片描述
3、const形参和实参
在这里插入图片描述
i相当于实参,ci相当于形参,可以推断,形参的顶层const被忽略掉了。当形参有顶层const时,传入常量或非常量都可以
在这里插入图片描述
函数名可以相同,但相同函数名的函数的形参列表不能一样,const int i,i的顶层const被忽略,两个函数重复定义了
尽量使用常量引用
普通引用会带来改变实参的麻烦,实参也不能是字面值或者是const对象
4、数组形参
输出数组中所有元素
在这里插入图片描述

在这里插入图片描述
数组引用形参
在这里插入图片描述
由内向外:arr是一个引用,它引用了一个数组,这个数组大小为10,数组元素的类型是int型。这个函数只能作用于大小为10的数组
传递多维数组
score[3][4]={. . .};
average(*score,12);
search(score,2);
void average(float *p,int n)
{
…p+11
}
void search(float (*p)[4],int n)
{
… * ( * (p+n)+i )
}
调用average时,实参为( *(score+0)+0 )
调用search时,实参为&score[0]
5、main:处理命令行选项
main函数的形参列表可不为空
在这里插入图片描述
argc表示数组中字符串数量,*argv[]是一个数组,它的元素是指针,指向字符串
6、含有可变形参的函数
编写处理不同数量实参函数的方法:
如果实参类型相同,可以传递一个名为initializer_list的标准库类型
如果实参类型不同,可以编写可变参数模板
initializer_list形参
在这里插入图片描述
和vector一样,initializer_list也是一种模板类型,必须说明列表所含元素类型
在这里插入图片描述
initializer_list对象中的元素永远是常量值,不可改变
在这里插入图片描述
在这里插入图片描述
第一次调用传入了三个值,第二次传入了两个值
形参列表中存在initializer_list对象的同时,也可以存在其它形参
省略符形参:
在这里插入图片描述
6-3返回类型和return语句
在这里插入图片描述
1、无返回值函数
返回值类型是void的函数不要求有返回值
在这里插入图片描述
swap函数中的return类似于break,可以使函数提前退出
在这里插入图片描述
2、有返回值函数
只要不是void函数,就必须有返回值,或者返回值的类型可以隐式地转换成函数的返回类型
在这里插入图片描述
}
第一个return返回两字符串是否相等的结果
第二个return返回两字符串是否有子集的关系
for循环结束后也应有一个return语句,返回两字符串是否有子集的关系
不要返回局部对象的引用或指针
函数完成后,它所占用的内存被释放,其中的引用将指向不再有效的内存区域
在这里插入图片描述
调用此函数将引发返回值未定义的行为
第一条return语句返回的是局部对象的引用
第二条return语句返回一个临时生成的string对象
返回类类型的函数和调用运算符
在这里插入图片描述
调用运算符的优先级与点运算符和箭头运算符相同,并且满足左结合律
引用返回左值
调用返回引用的函数返回左值,返回其它类型的函数返回右值
可以为返回非常量引用函数的结果赋值
在这里插入图片描述
return 0;
}
列表初始化返回值
在这里插入图片描述
如果函数返回的是内置类型,则花括号内最多有一个值
如果函数返回的是类类型,由类本身定义初始值如何使用
主函数main的返回值
返回0表示成功,返回其他值表示失败,非0值得含义由机器确定
为使返回值与机器无关,可以使用cstdlib头文件中定义的两个预处理变量分别表示成功与失败
在这里插入图片描述
在这里插入图片描述
递归
一个直接或间接地调用自己的函数是递归函数
使用递归求阶乘:
在这里插入图片描述
3、返回数组指针
函数不能返回数组,但是能返回数组的引用和指针
声明一个返回数组指针的函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用尾置返回类型
任何函数定义都能使用尾置返回,但尾置返回对返回类型复杂的函数最有效
尾置返回类型跟在形参列表后面,以符号->开头
在这里插入图片描述
func函数返回一个指针,指向大小为10的数组
使用decltype
如果知道函数返回的指针将指向哪个数组,可以使用decltype关键字声明返回类型
在这里插入图片描述
函数返回的是一个指针,它指的对象与odd一致,odd是一个数组,所有指针指向大小为5的数组
6-4函数重载
如果同一作用域内的几个函数函数名相同但形参列表不同,称函数为重载函数
main函数不能重载
如果函数名,形参列表相同,但是返回类型不同,只有第一个函数是对的
以下重载函数定义重复
在这里插入图片描述
重载和const形参
有顶层const的形参和没有顶层const的形参无法区分开来
在这里插入图片描述
如果形参是指针或引用,可以通过它们是指向常量还是非常量来区分,即通过底层const来区分
在这里插入图片描述
当传递非常量或者非常量的指针时,编译器优先选择非常量形参的函数
const_cast和重载
const_cast用于强制类型转换,只能改变运算对象的底层const
在这里插入图片描述
不论s1,s2是否为非常量,返回的都是常量引用
在这里插入图片描述
当实参s1,s2为非常量时,此函数内部调用了const版本的shorterString,返回的是非常量引用
调用重载函数有三种可能结果
在这里插入图片描述
在这里插入图片描述
重载与作用域
在这里插入图片描述
布尔值read覆盖了外层的read,print int覆盖了外层的两个print
在这里插入图片描述
如果这样声明,三个函数都能调用
6-5特殊用途语言特性
1、默认实参
在函数被调用的很多次中,某个形参被赋予了同一个值,称这个值为函数的默认实参
在这里插入图片描述
在这个函数中,为每一个形参都提供了默认实参,这个函数既能接纳默认值,又能接纳我们设定的值
当为一个形参提供了默认值时,形参列表里它后面形参也都要提供默认实参
使用默认实参调用函数
如下:
在这里插入图片描述
要想覆盖background的默认值,必须为ht和wid提供实参
在这里插入图片描述
第二个调用正确,是把char转换成了无符号数
在这里插入图片描述
默认实参声明
函数一般只声明一次,但函数可以多次声明。在给定作用域中的形参只能赋予一次默认实参。换句话说,函数的后续声明只能为没有被提供默认实参的形参提供默认实参,并且该形参右侧的形参都必须有默认值
第一次声明
在这里插入图片描述
声明重复
在这里插入图片描述
第二次声明
在这里插入图片描述
默认实参初始值
在这里插入图片描述
原来是24 80 ’ ',现在被修改为ht() 80 ’ ’
在这里插入图片描述
def被更新了,但wd未更新
2、内联函数和constexpr函数
内联函数和constexpr函数通常定义在头文件中
内联函数可避免调用函数的开销
在函数返回类型前加上关键字inline,可将函数声明成内联函数
在这里插入图片描述
constexpr函数
constexpr函数指能用于常量表达式的函数,它的返回类型及所有形参类型都必须是字面值类型,函数体中有且只有一条return语句
constexpr函数被隐式地指定为内联函数
在这里插入图片描述
允许constexpr的返回值不是一个常量
在这里插入图片描述
在这里插入图片描述
用非常量表达式调用scale函数时,返回值是一个非常量表达式
3、调试帮助
arrest预处理宏,预处理宏其实是一个预处理变量
在这里插入图片描述
arrest宏定义在cassert头文件中,无需提供using声明,使用的是arrest而不是std::arrest

NDEBUG预处理变量
arrest依赖于NDEBUG预处理变量,如果定义了NDEBUG预处理变量,则arrest什么也不做
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
6-6函数匹配
确定候选函数和可行函数
第一步:选定本次调用对应的重载函数集(候选函数的集合),候选函数需与被调用的函数同名,且其声明在调用点可见
第二步:考察调用提供的实参,选出可行函数(形参的数量及类型与调用提供的实参相对应)
寻找最佳匹配(在有的前提下)
含有多个形参的函数匹配
将每个函数的形参与实参的匹配程度一一做对比
在这里插入图片描述
6-7函数指针
在这里插入图片描述
要声明一个可以指向该函数的指针,把函数名换成指针即可
在这里插入图片描述
pf是一个指针,指向一个函数,函数的返回类型是布尔型
如果去掉括号
在这里插入图片描述
就变成一个指针函数,返回值是布尔型指针
可以为函数指针赋一个nullptr或值为零的整型常量表达式,来表示指针不指向任何函数
重载函数的指针
在这里插入图片描述
必须明确地指出选用哪个函数
在这里插入图片描述
函数指针形参
在这里插入图片描述
把函数作为实参使用,它会自动地转换成指针
在这里插入图片描述
返回指向函数的指针
在这里插入图片描述
F是函数类型(int型)
PF是指向函数类型的指针
在这里插入图片描述
直接声明f1:
在这里插入图片描述
1f1有形参列表,说明f1是一个函数,左边的 * 说明它的返回值是一个指针,指针又有形参列表,所以指针指向一个函数,该函数的返回类型是int型
也可以使用尾置返回类型的方式来声明:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值