概念
什么是调用运算符?
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表示成功,其他值表示失败