🔷 第六章 函数
📄 一句话概括

默认参数 = 给形参预先准备一个兜底值:调用时这个位置不填,函数就自动用它。写法是在参数表里写 = 值。两条硬规矩——默认值必须从最右边开始连续往左排,中间不能断;默认值只能写一处,通常写在声明里。

📝 本节和前面几节的关系

6.2.2 刚说完"实参个数必须和形参对得上",这一节是它的第一个例外:允许少传。默认参数是 C++ 相对 C 的改良之一(C 语言没有),专门服务于"大多数情况用常规值、偶尔才需要特殊值"这类函数。注意这里的 = 不是赋值(3.1.4 的 = 是运行时装盒子),而是"预先约定一个期初值"。

一、写法与效果

void show(char c = '*', int n = 5) {      // 两个参数都有默认值
    for (int i = 0; i < n; i++) cout << c;
    cout << endl;
}

show('*', 8);     // 全部自己给
show('#');        // 只给第一个,第二个用默认值 5
show();           // 都不给,全用默认值

一句话:默认参数就是"你不说,我就按老样子来"。

二、铁律:默认值必须从右往左连续排

void f(int a, int b = 2);              // ✅ 只有右边有默认
void f(int a, int b = 2, int c = 3);   // ✅ 从右往左连续
void f(int a = 1, int b);              // ❌ 编译错误:左边有默认、右边没有

为什么? 调用是按位置对号入座的:写 f(10) 时,10 只能填第一个参数。如果第一个有默认值、第二个没有,编译器就懵了——10 到底给谁?第二个参数又从哪来?填不上,所以不允许。

记忆法:把参数想成一排从左到右的座位。默认值只能从最右边那个座位开始,一个挨一个往左铺,中间不许留空位。

三、另一条规矩:默认值只能写一次

void printLine(char c = '-', int n = 20);    // ✅ 声明里给默认值

void printLine(char c, int n) {              // ✅ 定义里不再写
    for (int i = 0; i < n; i++) cout << c;
    cout << endl;
}

推荐:默认值写在声明里——因为调用方通常只看得见声明(回看 6.1.2:调用点能看见什么,决定了它能省什么)。声明和定义都写会报"重复指定默认参数"。

四、实例 02:调用带默认参数的函数

#include <iostream>
using namespace std;

void printLine(char c = '-', int n = 20);      // 声明里给默认值

int main() {
    cout << "标题" << endl;
    printLine();                 // 全默认:20 个 '-'
    cout << "正文" << endl;
    printLine('=');              // 只换字符:20 个 '='
    cout << "结束" << endl;
    printLine('*', 8);           // 都自己给:8 个 '*'
    return 0;
}

void printLine(char c, int n) {                 // 定义里不写默认值
    for (int i = 0; i < n; i++) cout << c;
    cout << endl;
}

看到什么算成功:

标题
--------------------
正文
====================
结束
********

这一篇顺手串起三件事:① 声明(6.1.2)与定义分离;② 默认值写在声明里;③ 调用可以少传。三处配合默契,main 里读起来就是"要什么就说什么"。

30 秒实验:把声明里那句改成不带默认值(void printLine(char c, int n);),然后调 printLine();——编译器会报"参数太少"。这正好复习 6.1.2:调用点只看得见声明,所以默认值写在声明里才管用。试完改回来。

五、常见误区

  1. "默认值的位置随便放"——必须从右往左连续。f(int a = 1, int b) 一定编不过。
  2. "声明和定义都写一遍更保险"——反而报错(重复指定默认参数)。写一处。
  3. "可以跳过中间那个、只传后面的"——做不到。位置必须从左往右依次填,没有 show('#', ) 这种写法。想灵活传参,得等第 8 章的"函数重载"与"带默认值的组合用法"(6.5 重载会给你另一条路)。
  4. "默认值可以是任意表达式"——默认值必须是编译期就能确定的值(字面量、const 常量等),不能是运行时才算出来的变量(如 n = x + 1 里的 x 是普通变量就不行)。本章按"常量"记最稳。
自测三问(点开对答案) 1. 默认参数解决什么问题?——让调用方在"大多数情况用常规值"时少写实参。 2. 默认值的位置有什么限制?——必须从最右边开始向左连续排列,中间不能断。 3. 有声明也有定义时,默认值写在哪?——写一处,通常写在声明里。

相关笔记