
1. 默认参数缺省参数在 C 中函数可以拥有默认参数也称为缺省参数。当调用函数时如果未提供某个参数则使用该参数的默认值。1.1 默认参数的声明与定义默认参数在函数声明中指定而不是在定义中。如果函数的声明和定义分开默认值应写在声明中。// .h 头文件 extern void func(int a 0); // .cpp 源文件 #include yang.h void func(int a 10) // 错误默认值应只在声明中指定 { printf(); }正确做法// .h 头文件 extern void func(int a 0); // .cpp 源文件 #include yang.h void func(int a) // 定义中不再写默认值 { printf(a %d\n, a); }1.2 默认参数的使用规则默认参数必须从右向左连续提供调用时从左向右传参不能跳过中间的默认参数。void func(int a 5, int b 4, int c 3, int d 2, int e 1) { printf(a %d b %d c %d d %d e %d \n, a, b, c, d, e); } int main() { func(); // a5,b4,c3,d2,e1 func(50, 40); // a50,b40,c3,d2,e1 // func(50, , 30); // 错误不能跳过 b return 0; }1.3 默认参数可以是表达式默认参数可以是常量、全局变量甚至是函数调用但必须是编译时可确定的表达式。int my_rand() { srand(time(nullptr)); return rand() % 100; // 0~99 } void func(int a, int b my_rand()) // 默认参数调用函数 { printf(a %d b %d \n, a, b); } int main() { func(1, 2); // a1, b2 func(12); // a12, b随机值 return 0; }2. 左值与右值C11 引入了值类别的概念每个表达式都有类型和值类别。左值 (lvalue)可以取地址的表达式通常有持久的状态右值 (rvalue)不能取地址的表达式通常是临时对象或字面量int main() { int a 10; // a 是 int 类型的左值 int* p nullptr; // p 是 int* 类型的左值 char ch a; // ch 是 char 类型的左值 const int b 20; // b 是 const int 类型的左值常性左值 a // 合法a 是左值 // 10; // 错误10 是右值 p // 合法p 是左值 // nullptr // 错误nullptr 是右值 b // 合法b 是左值常性左值 return 0; }3. 左值引用与右值引用3.1 左值引用传统的引用是左值引用只能绑定到左值。int main() { int a 10; int ra a; // 左值引用 const int cra a; // 左值常引用 const int b 20; // int rb b; // 错误不能将非 const 引用绑定到 const 对象 const int crb b; // 正确const 引用可以绑定到 const 对象 return 0; }3.2 右值引用C11 引入了右值引用只能绑定到右值。int main() { int a 10; int ra a; // 左值引用 const int rb a; // 左值常引用 int rr 10; // 右值引用绑定到字面量 10 // int rr2 a; // 错误不能将右值引用绑定到左值 cout rr endl; // 输出: 10 rr 100; // 可以修改 cout rr endl; // 输出: 110 const int crx 30; // const 左值引用可以绑定到右值 // 编译器会生成临时对象int tmp 30; const int crx tmp; return 0; }3.3 引用的特性int main() { int a 10; // 1. 引用必须初始化 int ra a; // 正确 // int rb; // 错误引用必须初始化 // 2. 不能引用引用C 中没有引用的引用 int* p a int** pp p // 指针的指针 // int rra ra; // 错误不能有引用的引用 // 3. 引用不能为 NULL // int rn NULL; // 错误 return 0; }4. 数组的引用数组的引用语法比较特殊需要括号int (rar)[n] ar;void funa(int *br, int n) // 数组退化为指针 { cout funa: br[5] size: sizeof(br) endl; // 输出指针大小 } void funb(int (rar)[5]) // 数组的引用保留数组类型信息 { cout funb (rar)[5] size: sizeof(rar) endl; // 输出数组大小 } int main() { const int n 5; int ar[n] { 12, 23, 34, 45, 56 }; // 1. 变量的别名 int a ar[0]; // 数组元素的引用 // 2. 数组的别名数组的引用 int(rar)[5] ar; // 必须指定正确的大小 cout main ar: size sizeof(ar) endl; // 20 (5 * 4) funa(ar, n); // 输出指针大小通常 4 或 8 funb(ar); // 输出数组大小 20 // 3. 指向数组的指针 int(*p)[n] ar; // 指向整个数组的指针 // 4. 指针数组的引用 int* br[n]; // 指针数组 int* (rbr)[n] br; // 指针数组的引用 return 0; }5. 类类型的引用引用不仅适用于内置类型也适用于用户自定义的类类型。class Int { // 类定义 }; int main() { Int obj; Int robj obj; // 类类型的左值引用 const Int crobj obj; // 类类型的 const 左值引用 const Int cobj; const Int rcobj cobj; // const 引用绑定 const 对象 // 对于类类型const 引用绑定右值时不会生成临时对象效率更高 const Int rtemp Int(); // 绑定到临时对象 return 0; }6. 总结默认参数在函数声明中指定从右向左连续提供左值可取地址右值不可取地址左值引用绑定左值右值引用绑定右值const 左值引用可以绑定左值和右值引用必须初始化不能为 NULL不能有引用的引用数组的引用需要特殊语法int (rar)[n] ar;引用适用于所有类型包括内置类型和用户自定义类型