1.参数传递:每次调用函数时都会重新创建函数的所有形参,此时所传递的实参将会初始化对应的形参。形参的初始化和变量的初始化一样,如果形参具有非引用类型,则复制实参的值;如果形参为引用类型,则只是实参的别名。
a.非引用形参:非引用形参表示对应实参的局部副本。这类形参的修改仅仅改变了局部副本的值。一旦函数结束,这些局部变量的值也就没有了。
i.指针形参:复制的是指针本身的值而不是指针指向对象的值。如果需要保护指针指向的值需要定义为指向const对象的指针,constint*p。
ii.const形参:不论形参为非引用的const类型还是非引用的非const类型,其实参都是可以const对象或非const对象。原因就是实参是以副本的形式传递,并不会改变原有的值。
iii.复制形参的局限性。不适宜复制实参的情况:1)当需要改变实参时;2)以大型对象作为实参时,复制对象所付出的时间和空间会很巨大;3)没有办法实现对象的复制时。其解决办法就是将形参定义为引用或指针类型。
b.引用形参:和变量的概念相似,只是实参的一个别名。
i.使用引用形参返回额外的信息。
ii.利用const引用避免复制,并且避免了对实参的修改。
iii.非const引用形参的限制。此时不能用const对象初始化,也不能一个右值或需要转换类型的对象初始化。只能与完全同类型的非const对象关联。
intincr(intval){……};
shortv1=0;
constintv2=42;
intv3=incr(v1);//error:v1isnotaint
v3=incr(v2);//error:v2isconst
v3=incr(0);//error:0isnotleftvalue
v3=incr(v1+v2);//additionisnotaleftvalue
c.数组形参
i.数组形参的定义。使用数组名时会自动转化为指向第一个元素的指针。下列三种定义都是等价的,形参类型都是int*。
voidfunc(int*){…};
voidfunc(int[]){…};
voidfunc(int[10]){…};
ii.形参的长度会引起误解。编译器忽略为任何数组形参制定的长度。编译器检查数组形参关联的实参时,只会检查实参是不是指针、指针的类型和数组元素类型是否匹配,而不会检查数组长度。
iii.通过引用传递数组。但形参为数组的引用时,编译器不会将数组实参转化为指针,而是其引用本身。数组的大小成为形参的一部分,将会被检查。
2.return语句
a.返回非引用类型。返回的是返回对象的副本,会有复制过程。
b.返回引用。返回对象本身。
c.不要返回局部对象的引用。
d.不要返回指向局部对象的指针。
3.内联函数
a.内联函数避免函数调用的开销。其原理是在调用点上“内联地”展开,有点类似于宏定义的概念,从而消除了函数调用的开销。
b.内联函数最好定义在头文件中。因为内联函数的定义对编译器而言必须是可见的,仅有函数原型是不能在调用点内联展开的。
c.内联说明对编译器来说只是一个建议,编译器可以选择忽略这个建议。大多数编译器不支持递归函数的内联,一个上千行的函数也不太可能在调用点内联展开。
d.类内定义的成员函数都会隐式地当作内联函数。
4.重载函数
a.在相同作用域的两个函数,如果具有相同的名字而形参不同,则成为重载函数。
b.函数不能仅仅基于不同的返回类型而实现重载。
c.重载与作用域。在函数中局部声明的名字将屏蔽全局作用域内声明的名字。这个关于变量名字的性质同样对于函数名成立。因此如果局部地声明一个函数,则该函数将会屏蔽而不是重载外层作用域中声明的同名函数。
5.指向函数的指针
a.函数指针是指向函数而非对象的指针。
b.函数指针指向的是某个特定函数类型,该函数类型由返回值和形参表确定,和函数名称无关。
bool(*pf)(conststring,conststring);
c.用typedef简化函数指针的定义
typedefbool(*cmpFunc)(conststring,conststring);
d.初始化和赋值。在引用函数名但没有调用函数时,函数名自动转化为指向函数的指针。下列初始化赋值皆有效。
typedefbool(*cmpFunc)(conststring,conststring);
boollengthCompare(conststringstr1,conststringstr2);
cmpFuncpf1=0;
cmpFuncpf2=lengthCompare;
cmpFuncpf3=lengthCompare;
pf1=lengthCompare;
pf2=pf1;
e.指向不同函数类型的指针不能转换。
本内容为随笔摘记,如有不正确之处还请谅解。
怎样治白癜风北京治疗白癜风