c++primer第五版第六章

第六章 函数

返回值

不能是数组和函数

自动对象

生命周期存在于{}内的对象

局部静态对象

只执行一次,一直有效;

内置类型的局部静态变量初始化为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返回函数类型,不返回指针
发布了19 篇原创文章 · 获赞 0 · 访问量 1250

猜你喜欢

转载自blog.csdn.net/qq_35459198/article/details/105342814