第8章 函数探幽

探索C++函数的更深层次奥秘!学习如何提升性能、共享数据,并编写更灵活、更通用的代码。

环节 1:内联函数 —— 程序的“快捷方式”

常规函数调用像一次“出差”,需要打包行李、出发、返回,有时间开销。内联函数则像一个“快捷键”,直接在原地完成任务,省去了来回奔波的时间。

调用开销模拟器 ⏱️

点击按钮,观察常规函数和内联函数在执行流程上的区别。

> 日志输出区...

#include <iostream> // 关键字 inline 建议编译器进行内联 inline double square(double x) { return x * x; } int main() { double a = 5.0; // 编译器可能会将这里替换为: // std::cout << "5的平方是: " << 5.0 * 5.0 << std::endl; std::cout << "5的平方是: " << square(a) << std::endl; return 0; }

环节 2:引用变量 —— 数据的“昵称”

引用就像给一个变量起了个“昵称”。你对昵称做任何事,实际上都是在对它本人操作。这让函数能直接修改外部的“正主”数据,而不是操作一个无关的“复制品”。

#include <iostream> // a 是 x 的昵称 (引用) // b 是 y 的昵称 (引用) void swap_by_ref(int & a, int & b) { int temp = a; a = b; b = temp; } int main() { int x = 10, y = 20; std::cout << "交换前: x=" << x << ", y=" << y << std::endl; swap_by_ref(x, y); // 把x, y本人传进去 std::cout << "交换后: x=" << x << ", y=" << y << std::endl; return 0; }

数据交换站 🤝

这里有两个盒子代表变量。点击按钮,调用引用函数 `swap_by_ref` 来交换它们内部的值。

变量 x
10
变量 y
20

环节 3:函数重载 —— “同名多艺”

函数重载就像一个多功能工具箱里的“万能扳手”。虽然都叫“扳手”,但它能根据你给的螺母大小(参数类型)自动调整形态,处理不同的任务。

智能数据打印机 📠

在下方输入不同类型的数据,然后点击打印。观察打印机如何智能地选择正确的处理程序(重载函数)。

> 打印机日志:

#include <iostream> #include <string> // 版本1: 打印整数 void print_data(int n) { std::cout << "打印整数: " << n << std::endl; } // 版本2: 打印浮点数 void print_data(double x) { std::cout << "打印浮点数: " << x << std::endl; } // 版本3: 打印字符串 void print_data(const std::string & s) { std::cout << "打印字符串: " << s << std::endl; }

环节 4:函数模板 —— “万能模具”

函数模板就像一个“万能模具”。你不用为整数、小数、字符串分别制作三种不同的交换机器,只需要设计一个“交换”的流程模具,C++就能根据你投入的材料(数据类型),自动生成一台专属的交换机。

#include <iostream> // T 是一个泛型,可以代表任何数据类型 template <typename T> void Swap(T & a, T & b) { T temp = a; a = b; b = temp; } int main() { int i1 = 10, i2 = 20; Swap(i1, i2); // 编译器自动生成 int 版 Swap double d1 = 3.3, d2 = 6.6; Swap(d1, d2); // 编译器自动生成 double 版 Swap return 0; }

万能交换机 🔄

输入任意两组数据(需类型相同),万能交换机将使用同一个模板来交换它们。

等待交换...

终点站:编程挑战

练习 1:安全交换(引用与内联)

任务:

编写一个内联函数 `safe_swap`,它接受两个 `long` 类型的常量引用参数。在 `main` 函数中,调用此函数并观察为什么无法交换它们的值。

预期知识点:

  • `inline` 关键字的使用。
  • `const` 引用是只读的,不能被修改。
点击查看参考答案
#include <iostream> using namespace std; // 声明为内联,并使用const引用 inline void safe_swap(const long & a, const long & b) { cout << "尝试交换..." << endl; // a = b; // 编译器将报错:不能修改 const 引用! cout << "无法修改常量引用。" << endl; } int main() { long num1 = 100L; long num2 = 200L; safe_swap(num1, num2); cout << "num1: " << num1 << ", num2: " << num2 << endl; return 0; }
练习 2:计算器重载

任务:

编写一个重载函数 `calculate`,实现以下三个版本:

  • 接受两个 `int` 参数,返回它们的**乘积**。
  • 接受两个 `double` 参数,返回它们的**和**。
  • 接受一个 `int` 和一个 `double`,返回它们的**差值**。

预期知识点:

函数重载,根据不同的参数列表(函数特征标)调用不同版本的函数。

点击查看参考答案
#include <iostream> using namespace std; // 1. int 版本 (乘积) int calculate(int a, int b) { return a * b; } // 2. double 版本 (和) double calculate(double a, double b) { return a + b; } // 3. int, double 版本 (差值) double calculate(int a, double b) { return a - b; } int main() { cout << "10 * 5 = " << calculate(10, 5) << endl; cout << "3.5 + 4.2 = " << calculate(3.5, 4.2) << endl; cout << "10 - 3.5 = " << calculate(10, 3.5) << endl; return 0; }
练习 3:数组求和(函数模板)

任务:

编写一个函数模板 `sum_array`,它能接受一个任意数值类型的数组和数组大小,并返回数组中所有元素的总和。

预期知识点:

函数模板的定义与使用,让一份代码适用于多种数据类型(`int[]`, `double[]` 等)。

点击查看参考答案
#include <iostream> using namespace std; // 模板函数,T代表数组元素的类型 template <typename T> T sum_array(T arr[], int size) { T total = T(); // 确保total初始化为T类型的零值 for (int i = 0; i < size; i++) { total = total + arr[i]; } return total; } int main() { int arr_int[] = {1, 2, 3, 4, 5}; double arr_double[] = {1.5, 2.5, 3.5}; int sum_i = sum_array(arr_int, 5); double sum_d = sum_array(arr_double, 3); cout << "整数数组的和: " << sum_i << endl; cout << "浮点数数组的和: " << sum_d << endl; return 0; }