文章目录
第六章 函数
返回值
不能是数组和函数
自动对象
生命周期存在于{}内的对象
局部静态对象
只执行一次,一直有效;
内置类型的局部静态变量初始化为0;
fun(){
static int i=0;
}
函数声明
void fun(int,int);
在头文件中声明函数和变量,在源文件中定义函数和变量。
[!]源文件要包含头文件
指针形参
fun(int *p){}//传递的是指向的对象的地址,不是指针的地址
[!]建议用int &来代替指针,避免拷贝,只读用const int &
引用形参
可以返回额外信息
const形参
非const形参会忽略顶层const
void fun(const int i);//只读,可以接受常量和非常量
error写法
void fun(const int i);//只读
void fun(int i);//只读
给形参赋值
类比变量的初始化
const int &a=42;//字面值可以给const int &
int &a=42;//error字面值不可以给int &
int &i=a;//error,const int &不可以给int &,但是可以给int
形参为常量引用
当形参不变时,尽量声明为常量引用,因为普通引用形参不能接收以下类型{const对象,字面值,需要转换类型的对象}
//如果内层确实无法使用常量引用就创建i的副本i2。
fun1(const int &i){
int i2=i;
fun2(i2){
//fun2 的形参是int&
}
}
数组形参
以指针的形式传递给函数
声明形式
fun(int*);
fun(int[]);
fun(int[10]);
数组尺寸
//传递头尾指针
fun(int*beg,int*en);
//使用标准库
int arr[2]={1,2};
fun(begin(arr),end(arr));
//////////////////////////////////
//字符串,'\0'结束
fun2(char*cp){
if(cp)
while(*cp){*cp++;}
}
//////////////////////////////////
//传递length
数组引用形参
f(int (&arr)[10]){...}
f(int &arr[10]){...};//error,数组里面有10个引用
多维数组的指针
//二维[10][10]
void print(int (*p)[10],int row){...}
//等价定义
void print(int p[][10],int row){...}
可变参数
实参类型相同传递:initializer_list标准库类型
实参类型不同:可变参数模板
省略符:用于和C交互的函数
initializer_list<T> lst;//元素是常量
initializer_list<T> lst{a,b,c};
lst2(lst);
lst2=lst;
lst.size();
lst.begin();//auto beg=lst.begin()..遍历
lst.end();
传递实参序列用{,}
可变参数+一般参数
//声明
void fun(ErrCode e,initializer_list<string> lst);
//传递实参
fun(ErrCode(0),{"dwa","dwa"})
省略符形参
C++和C代码衔接
这些代码使用了varargs的c标准库功能,
…只能出现在最后
void foo(para_list,...);
void foo(...);
return
void
return;
//可以返回另一个void fun2()
return fun2();
可以返回引用,就不用拷贝了
返回局部变量(包括字面值),指针都不行。函数结束,他们都不存在了。
返回对象,可以fun().成员
返回指针,可以fun()->mem
返回引用,可以当左值
返回列表{,,},可以为空
返回数组指针
方法一:别名
//arr是含有10个整数的数组
typedef int arr[10];
//等价写法
using arr =int[10];
//函数声明
arr*fun(int i);//返回值:arr的指针
方法二:声明
int arr[10];
int *p[10];//p是数组,里面元素是指针
int(*p2)[10]=&arr;//指向含有10个整数的数组
int (*fun(int i))[10];//返回值类型,数组int[10]的指针
/*
解读:*fun(int i)函数结果解引用,(*fun(int i))[10]是个数组,int (*fun(int i))[10]数组里面是int
*/
方法三:
auto fun(int i)->int(*)[10]
方法四:
int arr[10];
decltype(arr) * arrfun(int i){return &arr;}
重载
程序根据实参类型,调用同名函数。参数列表不同。
形参是指针或引用
形参分为常量对象和非常量对象
是底层const
fun(const int&);//接收常量和非常量,非常量可以转化成常量,反之不行
fun(int &);//非常量优先选择这个
fun(const int*);//接收常量和非常量,非常量可以转化成常量,反之不行
fun(int *);//非常量优先选择这个
const_cast和重载
const_cast是强制类型转换用的
现在要用返回值是const的函数,构建返回值是非const函数
const int &fun(const int &i){return i;}
int &fun(int &i){
auto &r=fun(const_cast<const int&>(i));//向const转型
return const_cast<int&>(i);}//再转回int
重载和作用域
声明的名字(包括变量和函数同名),内层的实体会覆盖外层同名的实体
默认实参
一个形参赋予了默认值,则其后的都有默认值
调用使用默认实参的函数
可以省略尾部的默认实参
默认实参的声明
可以多次声明,但是两次声明,同一个实参的默认值要相同。
而且一个形参赋予了默认值,则其后的都有默认值。已经声明的默认值可以不写,只写数值类型即可如int
默认实参的初始值
局部变量不能作为默认实参
函数的返回值可以做默认实参
int i=1;
int j=2;
int getnum();
void fun(int =getnum(),int=i,int=j);
fun2(){
i=2;//修改了默认实参i
int j=3;//覆盖外部j,但是局部变量不能作为默认实参
//默认实参j还是2
}
内联函数_提高性能
简单的,调用频繁,流程直接的函数,在返回值前面加inline,编译时可以把函数调用替换成函数体,而不是调用函数
constexpr函数_提高性能
函数调用替换成函数体
是隐式的inline函数
函数的返回值,形参都要是字面值类型,
返回值可以是常量也可以是非常量
constexpr int fun1(){return 33;}
constexpr int a=fun1();
inline函数和constexpr函数定义在头文件中
函数指针
指针替换函数名即可
int fun(int i);
//函数指针
int (*p)(int);
//两种定义方法
p=fun;
p=&fun;
//调用的两种方法
p(1);
(*p)(1);
//函数形参是函数指针的两种声明方法
fun2(int (*p)(int));//可以接收fun函数的指针
fun2(int p(int));
//调用fun2
fun2(fun);//函数名fun自动转换为指针
形参使用别名
/* 别名_函数类型 */
//取函数fun的类型
typedef int Nname(int i);//Nname是fun的函数类型
//取函数fun的类型的等价形式
typedef decltype(fun) Nname2;//Nname2是fun的函数类型
/* 别名_函数指针 */
typedef int (*pname)(int i);//pname是fun的函数指针
//取函数fun的指针的等价形式
typedef decltype(fun) *pname2;//pname2是fun的函数指针
/* 别名_使用 */
//两种方法,fun4的声明
fun4(Nname);//函数类型自动转换为函数指针
fun4(*pname);
返回值使用别名
/*返回值是函数指针*/
//类型别名
using F=int(int);//fun函数类型
using PF=int(*)(int);//fun函数指针
//返回值是函数指针的函数声明的两种方式
PF func(int);
F *func2(int);//不会函数类型自动转换为函数指针
//所以要加上*
不用别名直接声明返回值
方法一
int fun(int i);
//返回值为指向fun类型函数的指针
int (*func3(int))(int);
//func3(int)是函数声明,
//*返回指针,(*func3(int))(int)最后一个(int)是指针指向函数的形参列表
//第一个int是指针指向函数的返回值类型
方法二:尾置返回值声明
int fun(int i);
auto fun3(int)->int(*)(int);//返回值为指向fun类型函数的指针
方法三:decltype
decltype(fun) *fun5(int);//返回值为指向fun类型函数的指针
//注意:decltype返回函数类型,不返回指针