- 函数除了数组(严格定义上的数组,而不是指针什么之类的)都可以返回,返回值被存在指定的寄存器和内存单元中,然后由调用函数去获取该值,并拷贝下来,在这个过程中会检查类型是否匹配
- 为什么需要函数原型
- 原型描述了函数到编译器的接口,用于编译器检查调用函数是否满足原型中的一些规定,相比于查找定义,原型为编译器提供了便利,对于一些文件外的函数只需要引入包含原型的头文件即可,main()放在程序的开头就需要原型的支持。
- c++按值进行传递参数,argment表示实参,parameter表示形参(约定俗成的规定)
函数使用指针处理数组
- int* xxx和int xxx[]在这种情况下表意类似(注意当指针指向一个独立的值时,只能使用前者)
- 可以使用const来保护原始数组
- 函数传入数组时必须告知数组的名,数组的起始位置,数组的长度
- 使用区间来表示数组是STL容器中常见的作法(超尾),该做法使用两个指针来标识数组的一段区间,一般表现为迭代器
- 为了安全性考虑,常量地址不能被赋给非const 指针(有被修改的危险),所以在函数中尽量使用const指针,避免数据被修改和不可访问的问题
- const int *和int * const区别在于前者规定不能修改指向空间的值,而后者则是不能修改指向的空间,可以改变值
二维数组
- 使用行指针来做二维数组的传值即(*xx)[colSize]或者[][colSize]
- ar2[r][c]==((p+coffset)+roffset)
递归
函数指针
- 函数指针允许用户可以在不同的时间点上使用不同的函数来完成工作(动态编程)
- 获取函数的地址只需要获取函数名即可
- 注意声明函数指针时要加括号,否则就是返回值是个指针
- 调用时可以使用函数名或者解除引用方式
- 但需要调用多个函数时,可以声明函数数组(*p[funcSize])(arg[],....)
内联函数
- 常规函数需要在当前执行空间和函数地址之间进行来回跳跃,这种跳跃需要更多的时间和资源支持,而内联函数的使用中,编译器直接将函数代码编译进程序执行位置,按照执行顺序执行而无需跳转,代价是耗费更多的内存
- 关于如何选择,应该考虑函数调用机制的时间和函数执行的时间的差距,如果后者远大于前者,则不建议使用内联函数
- 内联函数使用inline作为关键字
- 注意内联函数不能递归,部分编译器甚至没有启用这种特性
- 在c中内联函数是通过宏来实现的(这也是内联函数的原始实现方式),但是宏不能安值传递而是将传递进来的表达式原样不动的放在内联函数中,然后进行运算,c++中则对函数按值传递的特性保持了一致
函数重载
- 函数重载的关键是函数的重载列表(function signature)
- 类型引用和类型本身是同一函数特征标,所以不能作为重载额依据,const也是
void sink(double & r1) //匹配可修改的左值
void sink(const double &r2) //匹配可修改(如果上面的存在,则优先级下降) 或者 const左右值
void sink(double && r3) //匹配右值
函数模板
- 如果需要将同一种操作用于多种数据类型,将会用模板来通用化这种的编程
- 使用模板前需要在函数声明前加上template<typename tp>,其中typename可以 用class代替
重载模板
- 模板函数的隐式实例化,显式实例化(指定函数模板类型),以及显式具体化(不使用模板,优先级高于模板实例化低于非模板定义),其中显式实例化和显示具体化不能共存,这两者的区别一是声明的不同(<>),二是前者采用模板的算法。而后者独立定义。
匹配规则
网友评论