c++基础第五次

函数

一个函数的定义包括:返回类型、函数名、多个形参、函数体。

函数调用:
1.用实参初始化函数定义的形参
2.将控制权转移给被调函数

return语句:
1.返回return语句中的值(如果有)
2.将控制权从被调函数转移回主调函数

实参的类型必须和相对应的形参类型匹配,顺序尽量一致。函数调用规定实参数量应该与形参数量一致,所以形参一定会被初始化。

形参列表中的形参通常用逗号隔开,每个形参都是含有一个声明符的声明。

任意两个形参名字不能同名,函数最外层作用域中的局部变量也不能使用与函数形参一样的名字。
即使形参不被函数使用,也必须为它提供一个实参。

局部对象
局部变量仅在函数的作用域中可见,同时局部变量还会隐藏在外层作用域中同名的其他所有声明中。

把只存在于块执行期间的对象称为自动对象,当块的执行结束后,块中创建的自动对象的值就变成未定义。
形参是一种自动对象

我们用传递给函数的实参初始化形参所对应的自动对象。
对于局部变量对应的自动对象:1. 如果变量定义本身含有初始值,就用这个初始值初始化,2.如果变量定义本身不含有初始值,执行默认初始化(内置类型的未初始化局部变量将产生未定义的值)

如何使局部变量的生命周期变长呢?
使用局部静态变量。局部静态对象在程序的执行路径第一次经过对象定义语句时初始化,直到程序终止才销毁(和普通局部对象生命周期不同),即使对象所在的函数结果结束执行也没有影响。

如果局部静态变量没有显式初始化,将执行值初始化,内置类型的局部静态变量初始化为0

函数声明

函数只能定义,但可以声明多次。如果一个函数永远不会用到,可以只有声明没有定义。
函数声明和函数定义的唯一区别就是函数声明无须函数体,用一个分号代替。

可以省略形参的名字,但一般不省略(更好理解函数功能)

之前说过,变量在头文件中声明,在源文件中定义,函数也是如此,在头文件中声明在源文件中定义。

定义函数的源文件应该把含有函数声明的头文件包含进来,编译器负责验证函数的定义和声明是否匹配。

参数传递:
每次调用函数时都会重新创建它的形参,并用传入的实参对形参进行初始化。

如果形参是引用类型,则它将绑定到对应的实参上,否则将实参的值拷贝到形参。
1.当形参是引用类型时,可以说对应的实参被引用传递或者函数被传引用调用,引用形参是它绑定的实参的别名(即引用形参是对应实参的别名)
2.当实参的值被拷贝到形参时,形参和实参是两个独立的对象,可以说实参被值传递或者函数被传值调用


使用引用避免拷贝
拷贝大的类类型对象或者容器对象比较低效,甚至有些类类型不支持拷贝操作。所以我们可以使用引用避免拷贝,函数只能通过引用形参访问该类型。

比较两个string对象的长度:

bool isShorter(const string &s1,const string &s2)
	return s1.size() < s2.size();

如果函数无须改变引用形参的值,最好将其声明为常量引用。

const 形参和实参

顶层const作用于对象本身。当用实参初始化形参时会忽略掉顶层const。即当形参中有顶层const,传给他常量对象或者非常量对象都可以。

有一个忽略顶层const的误区:

void fcn(const int i){
   }
void fcn(int i){
   }

上面两个函数第二个有错误,看似不同,但因为顶层const被忽略了,所以传入两个函数的参数可以完全相同。(重复定义了fcn(int i))

根据之前的初始化规则,可以使用非常量初始化一个底层const对象,同时一个普通的引用必须用同类型的对象初始化。
不能把const对象、字面值或者需要类型转换的对象传递给普通的引用形参。

数组形参
数组有两个特殊性质:
1.不允许拷贝数组 -----》无法使用值传递使用数组参数

2.使用数组名转换为指针,当我们为函数传递一个数组时,实际上传递的是指向数组首元素的一个指针。

形式不同但是函数等价:每个函数的唯一形参就是const int*类型的

void print(const int*);
void print(const int[]);
void print(const int[10]);

数组是以指针的形式传递给函数的,应该提供一些额外的信息

1.使用标记指定数组长度,数组本身包含一个结束标志
C风格字符串存储在字符数组中,而且在最后一个字符后跟着一个空字符,函数在处理C风格字符串时遇到空字符停止。

void print(const char *cp){
   
	if(cp)
		while(*cp)
			cout << *cp++;
}

2.使用标准库规范,成员函数begin()和end()

void print(const int *beg, const int *end){
   
	while(beg != end)
		cout << *beg++ << endl;
}

3.显式传递一个表示数组大小的形参

void print(const int ai[], size_t size){
   
	for(size_t i = 0; i!=size; ++i)
		cout << ai[i] << endl;
}
int j[] = {
   0,1};
print(j, end(j) - begin(j));

当函数不需要对数组元素执行写操作时,数组的形参应该是指向const的指针。
只有当函数确定要改变元素值时,才把形参定义为指向非常量的指针。

数组引用形参

void print(int (&arr)[10]){
   
	for(auto i : arr)
		cout << i <<endl;
}

f(int &arr[10]) 将arr声明为引用的数组,数组内是10个引用
f(int (&arr)[10]) arr是具有10个整数的整型数组的引用

限制了print函数的可用性,只能作用于大小为10的数组。

传递多维数组
真正传递的是指向数组首元素的指针,而首元素本身就是一个数组ÿ

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值