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

return 干两件事:交回一个值 + 立刻结束函数。三条规矩必须守:类型要对得上(对不上会被悄悄截断)、一次只能带一个值(本章带不出两个)、每条执行路径都要有 return(漏了就是垃圾值)。

📝 本节和前面几节的关系

这是 6.2 五篇的收尾,把"出口"讲完整。return 你在 2.1.6 就见过——main 里的 return 0 是交给操作系统的退出码。返回值是函数与外界交流的唯一正规出口(另一个是"改外部状态"的副作用,6.2.2 已经领教过)。

一、return 干的两件事

int add(int a, int b) {
    return a + b;                 // ① 把 a+b 的值交出去   ② 立刻结束本函数
    cout << "这行永远不会执行";      // 死代码(unreachable code)
}
事 说明
① 交回值 把 return 后面表达式的值(带类型)交给调用方
② 结束函数 后面的语句一句都不执行,直接回到调用点

return 之后那些执行不到的语句叫死代码,编译器通常会警告 unreachable code。写代码时 return 一般放在函数末尾或分支出口处,别在它后面还写东西。

二、三条规矩

规矩一:类型要对得上

int f() { return 3.9; }        // 3.9 被截断成 3(不是四舍五入)

返回值的类型转换规则和赋值完全一样(3.3.2):以"接收方"(这里就是返回类型)为准,小数被砍。

规矩二:一次只能带一个值

return a, b;                   // 实际返回的只有 b!这是 3.1.9 的逗号运算符

那怎么交回两个?本章没有正规解法。三条路记着以后用: 1. 打包成一个整体(第 7 章的结构体)再交回 2. 传地址进去,让函数直接改外部的变量(第 7 章指针、第 8 章引用) 3. 用现成的打包类型(后续章节的 pair、struct)

规矩三:每条执行路径都要有 return

int max2(int a, int b) {
    if (a > b) return a;
    // 如果 a <= b 走到这里——没有 return,交回的是垃圾值!   ← 错
}

正确写法:

int max2(int a, int b) {
    if (a > b) return a;
    return b;                  // 兜底:保证任何路径都有交代
}

三、动手 Demo:三种返回形态

#include <iostream>
using namespace std;

int max2(int a, int b) {                    // 有进有出
    if (a > b) return a;
    return b;                               // 保证每条路都有交代
}

bool isEven(int n) {                        // 返回 bool
    return n % 2 == 0;                      // 表达式的结果直接当返回值
}

void showMax(int a, int b) {                // 无返回值
    cout << "较大的数是 " << max2(a, b) << endl;
    return;                                 // 合法:表示提前收工(可省)
}

int main() {
    cout << max2(3, 9) << endl;                      // 9
    cout << isEven(7) << endl;                       // 0(默认输出 false 为 0)
    cout << boolalpha << isEven(8) << endl;          // true(2.4.3 的 boolalpha)
    showMax(100, 42);                                // 较大的数是 100
    return 0;
}

看到什么算成功:

9
0
true
较大的数是 100

请特别看一眼 return n % 2 == 0;——这是"算出来就是答案"的漂亮写法:n % 2 == 0 本身就是 bool 表达式(第三章),直接当返回值交出去。别写成 if (n % 2 == 0) return true; else return false;——那是啰嗦版,意思一模一样。

30 秒实验:把 max2 里的 return b; 注释掉,然后调 max2(3, 9)(此时 a > b 不成立,会走到函数末尾)——你会看到垃圾值(可能是 0,也可能是任意数)。这就是"漏 return"的现世报,和 2.3.2 的未初始化是同一种病。

四、常见误区

  1. "return 0 是输出 0 到屏幕"——不是,是交给操作系统的退出码(2.1.6),屏幕上什么都看不到。
  2. "返回值和屏幕输出是一回事"——完全不同。return x; 把值交给调用方;cout << x; 把值交给屏幕。函数里打印了,不代表它有返回值。
  3. "return 可以顺手把两个变量一起交回"——return a, b; 用的是逗号运算符,只有 b 被交回。这是最容易骗过眼睛的一行。
  4. "void 函数里 return 后面可以带值"——不行。void f() { return; } 合法(提前收工),void f() { return 5; } 编不过。
自测三问(点开对答案) 1. `return` 做的两件事?——交回一个值 + 立即结束函数(后面的都是死代码)。 2. `int f() { return 3.9; }` 返回什么?——3(被截断,不是四舍五入)。 3. 为什么每个分支出口都要写 return?——漏掉的那条路径会交回垃圾值,编译器可能只给警告。

相关笔记