一.参数缺省参数缺省指的是在函数的参数列表中针对某些或全部参数给其定义一个初始值当调用函数传参时如果不指定参数数值则会利用默认值进行函数参数的运算。函数参数缺省也可以成为参数默认。int Add(int x 1, int y 2) { return x y; } int main() { int a 0; int b 0; std::cin a b; std::cout a b \n; std::cout Add() std::endl; std::cout Add(a,b) std::endl; return 0; }例如上面这段程序定义了Add函数其内部有两个参数x和y默认值分别指定为1和2。如果调用Add函数不进行传参返回值结果就是12 3。如果进行传参则会返回传参的两个值相加的结果。需要格外注意的是在传参过程中只能从左向右依次传参不可以跳过某些参数进行传参。Add(a,b) Add(a) Add(); Add(,b)//错误例如上面这段代码前三种都是正确的情况可以全部传参可以只传a也可以都不传但不可以跳过a直接进行b的传参。函数参数的缺省分为全缺省和半缺省全缺省所有函数参数均以指定默认值如上例Add中参数x默认值为1y默认值为2两个参数都指定了默认值。半缺省半缺省指的是函数某些参数的参数值缺省需要格外注意参数的默认值需要从右向左进行缺省。Add(int x 1 , int y 2)//全缺省 Add(int x , int y 2)//半缺省同时需要注意如果函数的声明和定义分开写了那么函数参数的默认值只需要在头文件中给出即可。二. 函数重载在C语言中是不允许出现定义同名函数的情况。例如同时想实现一个交换函数Swap如果交换不同类型的值例如double和int则需要写两个Swap函数而在C语言中不可以同时命名为Swap需要对函数名称进行一定程度的区分例如Swap_int 、Swap_double。而在C中实现了函数的重载(重名)对函数的定义更加灵活。void Swap(int* x, int* y) { int tmp *x; *x *y; *y tmp; } void Swap(double* x, double* y) { double tmp *x; *x *y; *y tmp; }如上例所示利用同一个Swap名称可以同时定义出int和double两种类型的交换函数在真正进行函数调用时只需要传递不同的参数即可实现自动调用int或double类型的Swap函数。函数重载需要满足以下几种情况1.参数类型不同void Swap(int* x, int* y) { int tmp *x; *x *y; *y tmp; } void Swap(double* x, double* y) { double tmp *x; *x *y; *y tmp; }参数类型不同只需要传参的过程中进行不同类型参数的传递即可不会引起歧义。2.参数个数不同void f() { cout 1 endl; } void f(int a 1) { cout a endl; }第一个函数直接进行调用即可而第二个参数需要进行传参。但对于这个示例需要注意由于函数缺省值的存在如果调用第二个函数的过程中参数缺省就会和第一个函数发生歧义程序会编译报错。3.参数类型顺序不同void f(int a, char b) { cout a b endl; } void f(char a, int b) { cout a b endl; }本质就是参数类型不同。4.返回值的不同不能作为函数的重载条件。int f() { return 1; } double f() { return 1.1 }如该例进行函数调用的时候无法判断调用哪个f()程序会编译报错。三.引用引用是为已经存在的变量起了一个别名编译器并没有为它实际开辟空间它和它所引用的变量共同指向同一块内存空间。基本语法如下int main() { int a 0; int b a; //在这里b就是a的引用b就是a的另一个名字 cout a endl; cout b endl; //从这里可看出a和b指向同一块空间 int c b; //c是b的别名同样c也是a的别名最终都是指向a这块空间 cout c endl; //三者地址相同 int x 1; c x; cout a endl;//对引用赋值同样也会改变原数值 cout c endl;//指向的空间并没有改变。 return 0; }如该例所示首先创建了一个变量a然后对a创建了一个引用b引用的操作符和取地址操作符相同。输出a和b的地址可以发现他们指向了同一块区域。再对b创建一个引用c那么a b c同时指向同一块区域它们三者的数值、地址均相同。如果此时再定义一个新变量x然后进行赋值操作c x会发现a b c 的数值均发生改变而地址不发生改变。由该例子可以得出一些结论1.引用在创建时必须要初始化。2.一个变量可以有多个引用3.引用一旦有了一个实体就不能改变。3.1引用的实际应用//引用的使用场景和使用方式 typedef struct Slt { int* arr; int size; int capacity; }Slt; void Swap(int x, int y) { int tmp x; x y; y tmp; } void SltInit(Slt s , int n 4)//缺省参数为4默认创建4个空间的大小 { int* tmp (int*)calloc(n, sizeof(int)); if (tmp NULL) { exit(EXIT_FAILURE); } //传递的是引用不再是指针因此对结构体成员的访问用操作符 . s.arr tmp; s.capacity 4; s.size 0; } void SltPush(Slt s , int x) { if (s.size s.capacity) { s.capacity * 2; int* tmp (int*)realloc(s.arr, s.capacity * sizeof(int)); if (tmp NULL) { perror(Push Realloc error); exit(EXIT_FAILURE); } s.arr tmp; tmp NULL; } s.arr[s.size] x; } //返回类型为引用 int SlSearch(Slt s, int i) { assert(i s.capacity); return s.arr[i]; } int SlSearch1(Slt s, int i) { assert(i s.capacity); return s.arr[i]; } int main() { int a 10; int b 20; Swap(a, b); cout a b endl; //1.进行函数传参起到类似于指针的作用 //在传参时传递的参数为引用甚至没有开辟出空间相比于指针还要节省空间 //尤其是在结构体传参的过程中。 Slt s1 { 0 }; SltInit(s1);//传参为s1在函数中形成一份引用从而可以实现直接对结构体变量的操控。 SltPush(s1, 1); SltPush(s1, 2); SltPush(s1, 3); SltPush(s1, 4); SltPush(s1, 5); cout endl; for (int i 0; i s1.size; i) { cout s1.arr[i] endl; } cout endl; //如果直接返回值为int类型其实际存储到一个新的临时变量中 //该变量属于被const修饰不能直接修改 //cout SlSearch(s1, 3) endl; err //如果返回的是引用类型甚至没有进行空间的开辟 //可以进行修改 cout SlSearch1(s1, 3) endl; return 0; }首先简单创建一个顺序表实现了初始化和基本插入数据的操作。利用在C中新学到的缺省参数可以默认给顺序表开辟4个整形空间的大小如果有额外需要可以在最开始就指定开辟多大空间的顺序表。1.函数参数传引用函数参数传引用可以起到类似于指针的作用。在 SltInit 和 SltPush函数中传递的参数均为结构体的引用所以其并没有在内存中实际开辟出一个结构体大小的空间而是传递一个已有结构体的别名。在函数内部的操作中由于不是地址所以需要利用“ . ”的操作符来实现对结构体对象的访问。2.返回类型为引用函数的返回值类型为引用。例如在函数 SlSearch(返回 int 整形) 和 SlSearch1返回 int 引用。在SlSearch函数最后返回的是一个整形数据其具体存储在一个临时变量中然后进行返回该临时变量由系统对其进行常量化处理不能修改。而如果利用SlSearch1函数其返回类型为该值得一个引用在这个过程中并没有新的临时变量被开辟而仅仅是原变量得一个别名所以其可以被修改。但需要格外注意的是如果返回类型为引用处理不好的情况下容易形成空引用int f1() { int ret1 0; return ret1;//如果在主程序中调用了这个函数就会形成野引用 } int f2() { return 1; } int main() { int a f1();//此处就会形成野引用 int b f1(); cout a endl; cout b endl;//虽然这里也可以输出0但并不稳定 int c f2(); cout a endl; cout b endl;//野引用在其他语句或函数调用后可能就会出问题。 return 0; }例如该示例定义函数 f1返回一个ret1的引用而 ret1 为 f1 函数中定义出的临时变量在 f1调用结束之后f1的函数栈帧销毁而返回的引用对象仍然为该块空间的值所以会形成野引用导致程序运行不稳定。虽然可能对其进行输出仍然能输出原始 ret1 的结果但是如果运行其它程序它的结果可能就会发生变化。所以一个函数可以返回引用类型的前提是它所返回变量的引用该变量在函数运行结束后并没有销毁。