c++primer_6:函数

概念

什么是调用运算符?

func() 调用时写的小括号就是调用运算符

什么是局部变量?

形参和函数体内部定义的变量

局部变量、自动对象、局部静态对象的区别?

从作用域的角度来看,自动对象和局部静态对象都满足局部变量的形式
从生命周期的角度来看,后两者完全不同。

默认初始化和值初始化的区别?

默认初始化不会对定义在函数体内部的内置类型变量初始化为0,而值初始化会。
如果变量属于某种类类型,那么值初始化采用默认初始化的策略。这时,如果类仅支持显式初始化,将会引发错误。

什么是函数原型?

就是函数声明,用封号代替了函数体。
规定了函数调用所需要的全部信息。

引用传递和值传递的区别?

关键在于形参是否是引用类型。

如何理解以下两句的冲突?

void func ( const int i );
void func ( int i );
//这两句是冲突的,假设存在以下情况:
int a;
const int ca;
//那么在调用func(a)和func(ca)的时候,都是只关心a和ca的值而已,而不关心a或者ca这两个实参的类型,也就是说,实参的顶层const被忽略了。

initializer_list如何使用?
在这里插入图片描述
在这里插入图片描述
什么是函数匹配(重载确定)?

函数调用与一组重载函数中的某一个关联起来。

constexpr函数的应用?

constexpr用来让编译器来验证一个变量的值是不是一个常量表达式
常量表达式是指仅由字面值、constexpr变量、constexpr函数组合成的表达式,可以在编译期间直接得到结果。
constexpr函数指由常量表达式实现出来的函数。其返回类型和所有形参的类型都是字面值类型。必须有且只有一条return。形参可以是非常量,实参必须是常量。
在这里插入图片描述
注意:

int a = scale(i);	//这样写没有问题,虽然scale是constexpr函数,但是这条语句不会对它进行检查,它返回的也不是常量表达式,返回值在编译期间无法计算,其实这时就没必要将它声明为constexpr函数。
constexpr int a = scale(i);	//这样写就会报错,因为scale处于constexpr上下文中,编译器会进行检查。

描述

描述函数的调用过程?

  • 实参初始化形参
  • 主调函数中断
  • 控制权转移

描述return的过程?

  • 返回值,这时尚未回到主调函数的相关语句中,可以理解为创建了一个临时的变量。
  • 控制权转移
  • 完成主调函数中调用表达式所在的语句

注意

  • 形参和实参类型必须匹配,或能转换
  • 函数的返回类型不能是数组类型或者函数类型,但是可以是指向数组或函数的指针。
  • 自动对象不会进行值初始化。局部静态对象才会。
  • 局部静态对象的销毁时间是:程序终止时。
  • 函数只能定义一次,可以声明多次。
  • 数组传递给函数以指针的形式,而函数无法仅通过这个指针来获悉数组的尺寸。
  • 要想使用数组引用传递,而不是使用指针来传递,需要注意:
func(const int a[]);
func(const int *a);
//上面两者等价
func(const int (&a)[10]);
//上面这种方法是数组,现在我们还没有能力接收任意大小的数组,只能接收大小为10的数组。
  • 大多数类型的对象在传递给省略符形参时都无法正确拷贝。
  • 不要返回局部对象的引用或指针
  • 内外层出现同名的函数时,内层屏蔽外层,与参数类型无关,即时外层比内层更加匹配也会被屏蔽;
  • 局部变量不能作为默认实参

最佳实践

  • 在C++中,建议使用引用类型的形参代替指针。
  • 应该尽可能使用引用避免拷贝。
    • 这里所说的尽可能,是指在不对实参造成影响的前提下。
    • 避免拷贝的原因:减少开销、尊重不支持拷贝的类
    • 最好使用常量引用
  • 形参使用常量引用的优点
    • 避免函数体内部的修改影响外部
    • 如果不使用常量引用,那么const对象、字面值或者需要类型转换的对象将无法传递给引用形参。
    • 在函数的嵌套中,形参传递链可能会因为某一个不是常量而断开。
  • 数组作为参数传递,最好指定其大小
    在这里插入图片描述
  • 数组引用传递,可以方便进行范围for循环。注意&arr用小括号括起来
    在这里插入图片描述
  • 如果想要返回数组,应该返回数组的指针,因为数组不能被拷贝
方法一:使用类型别名:
typedef int tenIntArray[10];
tenIntArray* func(int i);
方法二:尾置返回类型:
auto func(inti) -> int(*)[10];
方法三:使用decltype:
int arr[] = {1,2,3};
decltype(arr) *pArr (int i);
  • 对于流程直接、频繁调用的函数,可以声明为内联函数。
    • 和语句相比,函数调用多了一些开销:保存寄存器、控制权转移、拷贝实参、恢复寄存器。
    • 内联函数和constexpr函数定义在头文件中。
  • 调用重载函数如果出现了二义性调用(往往出现在有多个形参的情况中),或者出现了实参强制类型转换才能匹配某个重载函数的情况,那说明我们设计的重载不合理。

了解

  • 可以使用void表示函数没有形参
  • 形参可以不命名,但是必须提供实参
  • 可以将引用形参看作特殊的返回值,这是多返回函数的一种实现形式。
  • 省略符形参一般只用于与C函数交互的接口程序
  • 调用一个返回引用的函数会得到左值
  • main函数虽然是int类型,但是可以不写return语句(不建议)。return语句由编译器隐式插入。返回0表示成功,其他值表示失败
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值