C++学习笔记(五)----关于参数传递(2)
数组形参
1.如果形参是数组(非引用),那么编译器会忽略定义形参时指定的长度,所以就没有必要指定长度了.但是这时我们就应该确保调用函数时不会造成数组访问越界,课本上介绍了以下3种方式
(1)标识符.就是在数组的结尾加上一个标识符,然后在函数调用的时候判断是否到了标识符.典型的例子就是C风格字符串(以'\0'结束).
(2)传递两个指针给函数.一个是指向数组第一个元素的指针(比如数组名);另一个是指向数组最后一个元素的下一个地址的指针.这样在函数里通过判断是否已处理到数组最后一个元素的下一个地址来决定是否结束调用.这是一种比较标准的用法,不需要对数组做添加标识符之类的特殊处理.
(3)除了传递向数组第一个元素的指针,还向函数传递数组的大小(回忆一下怎么得到数组的大小),这也是一种很普遍的用法.
2.如果形参是数组的引用,那么编译器则会检查实参的大小与形参的大小是否匹配.如这样的函数
void printValues(int (&arr)[10]){...}
就只会接受长度为10的整形数组作为实参.
3.多维数组(比如二维数组,第一维称为行,第二维称为列,int ar[3][4]就是3行4列,也就是有3行元素每行4个.)的传递,还是用课本的例子:
viod printValues(int (matrix*)[10],int rowSize){...}
这里的形参就是一个二维数组,第一维的值不指定(可以通过rowSize保证安全性),第二维的值确定为10.即这个二维数组每行有10个元素,具体有多少行不指定.
--------------------------------------
main的参数
主函数的main的参数形式是规定好了不能改的:
int main(int argc,char *argv[]){...}
argc表示后面输入字符串的数目,后面就输入字符串用空格隔开.
我使用的vc++ 2008,可以在"项目->属性->调试->命令参数"里面写上main的实参,argc不用输入的,另外argv[0]也是编译器指定好了(程序名),所以你写入的第一个字符串就是argv[1]...
-------------------------------------
return
1.返回类型为void类型的函数,可以return fun(...),其中fun()也是个返回void类型的函数.
2.课本第213页的例子有错,在while循环里面,应该对i做加一操作,可以改为if(str1[i]!=str2[i++]).
3.一般的函数时返回非引用类型,返回的值用于初始化在调用函数处创建的临时对象.而当函数返回引用类型时(在函数名前加&),返回的就是对象本身.引用返回的是左值.通过执行一个返回引用类型的函数,我们得到了希望得到的那个对象,然后就可以立即对它赋值.
4.不能返回函数体内的局部对象的引用,那样的话一旦函数执行完毕,这个局部对象就没有了,那还搞什么搞...同理,不能返回指向局部对象的指针.
--------------------------------------
默认实参
1.规则一:如果函数中有个形参具有默认实参,那么这个形参后面的形参都必须得有默认实参;规则二:调用函数的时候,如果某个参数不能使用默认实参,那么这个参数前面的所有参数也都不能使用默认实参.因此,我们得把最可能使用默认实参的参数放到最后面.
2.默认实参可以是任何适当类型的表达式.
3.在一个文件中,只能为一个形参指定默认实参一次.
--------------------------------------
局部对象
1.在函数体内定义的变量,在执行定义语句的时候出生,函数调用结束,这个对象的生命期也就结束了.
2.一个函数体内定义的变量,如果定义时加上static,那么它就是一个静态局部对象.当执行这个定义语句的时候它出生了,函数调用结束它还活着,程序结束了它的生命期才结束.而且静态变量在整个程序执行过程中只初始化一次.
---------------------------------------
内联函数
1.调用函数前有很多工作要做:先保存寄存器,并在返回时恢复;复制实参;程序再转向一个新位置执行.这样看起来开销不小啊.
2.如果一个函数很短,我们又经常要调用它.那么可以将这个函数指定为内联函数.例如:
inline int fun(int &a,int &b){...}
那么函数fun()就是个内联函数.程序编译的时候碰到用到内联函数的地方就会将它的代码自动展开.
3.应该吧内联函数放在头文件中定义,我看就专门弄一个头文件放内联函数吧.