一、缺省参数默认参数1. 什么是缺省参数缺省参数就是声明 / 定义函数时为形参指定一个默认值。调用函数时如果没传实参就用这个默认值传了实参就用传入的值。 也叫 “默认参数”分为全缺省所有形参都给默认值和半缺省部分形参给默认值。2. 核心规则半缺省参数必须从右往左连续给不能间隔跳跃。调用带缺省参数的函数时实参必须从左到右依次给不能跳跃传参。函数声明和定义分离时缺省参数不能同时在声明和定义中出现必须只在声明里给。示例// 声明时给缺省值 void func(int a, int b 10, int c 20); int main() { func(1); // a1, b10, c20 func(1, 2); // a1, b2, c20 func(1,2,3);// a1, b2, c3 return 0; } // 定义时不再写缺省值 void func(int a, int b, int c) { // ... }二、函数重载1. 什么是函数重载C 支持在同一作用域中定义同名函数但这些函数的形参必须满足参数个数不同或参数类型不同或顺序不同。这种特性让函数调用表现出 “多态行为”使用更灵活。C 语言不支持同一作用域的同名函数。示例int add(int a, int b) { return a b; } double add(double a, double b) { return a b; } int add(int a, int b, int c) { return a b c; } int main() { add(1, 2); // 调用int版 add(1.5, 2.5); // 调用double版 add(1, 2, 3); // 调用三参数版 return 0; }三、引用的概念与用法1. 什么是引用引用不是定义新变量而是给已存在的变量取一个别名。编译器不会为引用开辟额外内存空间它和原变量共用同一块内存。语法类型 引用别名 引用对象;示例int a 10; int b a; // b是a的别名 cout a endl; // 地址和a相同 cout b endl;2. 引用的四大功能① 做函数形参修改实参的值// 错误值传递无法交换void swap(int p1, int p2) {int tmp p1;p1 p2;p2 tmp;}// 正确引用传递直接修改实参void swap(int p1, int p2) {int tmp p1;p1 p2;p2 tmp;}② 做函数形参减少拷贝提高效率当参数是大型结构体 / 类时用引用可以避免整个对象拷贝提升性能struct A { /* 大型数据 */ }; // 传值拷贝整个A对象 void func(struct A aa) {} // 传引用只传别名不拷贝 void func(struct A aa) {}③ 做返回值类型修改返回的对象传值返回会生成临时变量无法被修改传引用返回可以直接修改原对象// 传值返回返回临时变量无法被赋值 int SLAt(SL sl, int i) { assert(i sl.size); return sl.a[i]; } // 传引用返回返回元素的引用可以直接修改 int SLAt(SL sl, int i) { assert(i sl.size); return sl.a[i]; } int main() { SL s; SLAt(s, 0) 10; // 传引用返回时合法传值返回会报错 return 0; }④ 做返回值类型减少拷贝提高效率返回大型对象时引用返回避免拷贝临时对象提升性能。3. 引用的安全问题不能返回局部变量的引用如果函数返回局部变量的引用函数结束后局部变量的内存会被销毁引用就会变成 “野引用”导致未定义行为。错误示例int func() { int ret 0; // 局部变量 return ret; // 错误返回局部变量的引用 } int main() { int x func(); cout x endl; // 内存已销毁结果不可预测 return 0; }原因图解func() 栈帧 ┌─────────────┐ │ ret 0 │ ← 函数结束后这块内存被销毁 └─────────────┘ main() 栈帧 ┌─────────────┐ │ x ret │ ← ret已销毁x指向无效内存 └─────────────┘四、指针引用的应用链表头结点修改当需要在函数中修改链表头指针时用指针引用可以直接修改原指针避免二级指针的复杂写法typedef struct ListNode { int val; struct ListNode* next; } LTNode, *PNode; // 用指针引用修改头结点 void ListPushBack(PNode phead, int x) { PNode newnode (PNode)malloc(sizeof(LTNode)); newnode-val x; newnode-next NULL; if (phead NULL) { phead newnode; // 直接修改原头指针 } else { // ... 找尾结点插入 } } int main() { PNode plist NULL; ListPushBack(plist, 1); ListPushBack(plist, 2); return 0; }五、总结特性核心作用缺省参数简化函数调用给参数提供默认值注意声明和定义不能同时给缺省值函数重载同一作用域定义同名函数通过形参区分实现 “多态调用”引用变量的别名可用于修改实参、减少拷贝、修改返回对象但不能返回局部变量引用
【C++入门笔记】缺省参数、函数重载与引用详解
一、缺省参数默认参数1. 什么是缺省参数缺省参数就是声明 / 定义函数时为形参指定一个默认值。调用函数时如果没传实参就用这个默认值传了实参就用传入的值。 也叫 “默认参数”分为全缺省所有形参都给默认值和半缺省部分形参给默认值。2. 核心规则半缺省参数必须从右往左连续给不能间隔跳跃。调用带缺省参数的函数时实参必须从左到右依次给不能跳跃传参。函数声明和定义分离时缺省参数不能同时在声明和定义中出现必须只在声明里给。示例// 声明时给缺省值 void func(int a, int b 10, int c 20); int main() { func(1); // a1, b10, c20 func(1, 2); // a1, b2, c20 func(1,2,3);// a1, b2, c3 return 0; } // 定义时不再写缺省值 void func(int a, int b, int c) { // ... }二、函数重载1. 什么是函数重载C 支持在同一作用域中定义同名函数但这些函数的形参必须满足参数个数不同或参数类型不同或顺序不同。这种特性让函数调用表现出 “多态行为”使用更灵活。C 语言不支持同一作用域的同名函数。示例int add(int a, int b) { return a b; } double add(double a, double b) { return a b; } int add(int a, int b, int c) { return a b c; } int main() { add(1, 2); // 调用int版 add(1.5, 2.5); // 调用double版 add(1, 2, 3); // 调用三参数版 return 0; }三、引用的概念与用法1. 什么是引用引用不是定义新变量而是给已存在的变量取一个别名。编译器不会为引用开辟额外内存空间它和原变量共用同一块内存。语法类型 引用别名 引用对象;示例int a 10; int b a; // b是a的别名 cout a endl; // 地址和a相同 cout b endl;2. 引用的四大功能① 做函数形参修改实参的值// 错误值传递无法交换void swap(int p1, int p2) {int tmp p1;p1 p2;p2 tmp;}// 正确引用传递直接修改实参void swap(int p1, int p2) {int tmp p1;p1 p2;p2 tmp;}② 做函数形参减少拷贝提高效率当参数是大型结构体 / 类时用引用可以避免整个对象拷贝提升性能struct A { /* 大型数据 */ }; // 传值拷贝整个A对象 void func(struct A aa) {} // 传引用只传别名不拷贝 void func(struct A aa) {}③ 做返回值类型修改返回的对象传值返回会生成临时变量无法被修改传引用返回可以直接修改原对象// 传值返回返回临时变量无法被赋值 int SLAt(SL sl, int i) { assert(i sl.size); return sl.a[i]; } // 传引用返回返回元素的引用可以直接修改 int SLAt(SL sl, int i) { assert(i sl.size); return sl.a[i]; } int main() { SL s; SLAt(s, 0) 10; // 传引用返回时合法传值返回会报错 return 0; }④ 做返回值类型减少拷贝提高效率返回大型对象时引用返回避免拷贝临时对象提升性能。3. 引用的安全问题不能返回局部变量的引用如果函数返回局部变量的引用函数结束后局部变量的内存会被销毁引用就会变成 “野引用”导致未定义行为。错误示例int func() { int ret 0; // 局部变量 return ret; // 错误返回局部变量的引用 } int main() { int x func(); cout x endl; // 内存已销毁结果不可预测 return 0; }原因图解func() 栈帧 ┌─────────────┐ │ ret 0 │ ← 函数结束后这块内存被销毁 └─────────────┘ main() 栈帧 ┌─────────────┐ │ x ret │ ← ret已销毁x指向无效内存 └─────────────┘四、指针引用的应用链表头结点修改当需要在函数中修改链表头指针时用指针引用可以直接修改原指针避免二级指针的复杂写法typedef struct ListNode { int val; struct ListNode* next; } LTNode, *PNode; // 用指针引用修改头结点 void ListPushBack(PNode phead, int x) { PNode newnode (PNode)malloc(sizeof(LTNode)); newnode-val x; newnode-next NULL; if (phead NULL) { phead newnode; // 直接修改原头指针 } else { // ... 找尾结点插入 } } int main() { PNode plist NULL; ListPushBack(plist, 1); ListPushBack(plist, 2); return 0; }五、总结特性核心作用缺省参数简化函数调用给参数提供默认值注意声明和定义不能同时给缺省值函数重载同一作用域定义同名函数通过形参区分实现 “多态调用”引用变量的别名可用于修改实参、减少拷贝、修改返回对象但不能返回局部变量引用