CC++ & Algorithm

形参与实参

中等5
语言版本:C++
概述:理解函数定义中的“形参”和调用时传入的“实参”之间的区别,就像快递单上的收件人名字与实际收货人的关系。

形参和实参:函数中的“填空格”与“真答案”

当你填快递单时,会在收件人一栏写上“张三”。快递员送包裹时,真正收包裹的人是张三本人。这里的“收件人名字”就像形参,它只是一个占位符,告诉你这里需要填一个名字;而“张三本人”就是实参,是真正实际的值。

在C++函数中,形参和实参就是这种关系。理解它们,你就能看懂函数的“输入口”是怎么回事。


什么是形参?

形参(形式参数)是在定义函数时写在括号里的变量。它没有具体的值,只是告诉编译器:“这个函数将来需要接收几个数,每个数是什么类型”。形参就像一张表格里预留的空格,等你往里填内容。

// 函数定义:形参 width 和 height 都是 double 类型,目前没有具体数值
double rectangleArea(double width, double height) {
    return width * height;
}
  • widthheight 是形参,它们存在于函数定义的那一行的括号里。
  • 在函数内部,你可以使用形参的名字进行计算,就像使用普通变量一样。
  • 形参只在函数内部有效,函数执行完毕就会消失。

生活类比:就像数学公式 面积 = 长 × 宽 中的“长”和“宽”,它们代表未知数,等着你代入具体的数字。


什么是实参?

实参(实际参数)是在调用函数时真正传给函数的数值或变量。实参就是快递单上“张三本人”那个具体的收货人。例如:

double length = 5.0, width = 3.0;
// 调用函数:传入两个实参 length 和 width(它们的值是 5.0 和 3.0)
double area = rectangleArea(length, width); 
cout << area << endl;   // 输出 15

// 也可以直接传数字(字面量)
cout << rectangleArea(7.2, 4.5) << endl;  // 输出 32.4
  • lengthwidth 是变量,调用时它们的值复制给形参。
  • 7.24.5 是字面量,也是实参。
  • 实参可以有任意多个,只要类型和数量与形参一一对应。

形参和实参的“复制”关系

当函数被调用时,实参的会复制一份给对应的形参。就像你把快递单上的名字写下来,快递员拿着单子去找那个人,而不是把单子本身给那个人。所以:

  • 形参得到了实参的副本
  • 在函数内部修改形参,不会影响函数外部的实参(除非用引用,那是后话)。

看这个例子:

#include <iostream>
using namespace std;

void changeValue(int x) {   // 形参 x
    x = 100;                // 修改形参
    cout << "函数内部 x = " << x << endl;
}

int main() {
    int num = 5;            // 实参 num = 5
    cout << "调用前 num = " << num << endl;   // 输出 5
    changeValue(num);       // 把 num 的值(5)复制给 x
    cout << "调用后 num = " << num << endl;   // 输出 5(没变!)
    return 0;
}

输出:

调用前 num = 5
函数内部 x = 100
调用后 num = 5

你看,num 的值并没有变成 100,因为函数修改的是形参 x 的副本,实参 num 自己还是原来的 5。这就像你叫“张三”去帮你拿快递,但快递员把包裹给了另一个也叫“张三”的人,真正的你还是没拿到。


生活中的更多例子

例子1:计算零花钱中的“折扣价”

假设你每天有零花钱 allowance 元,妈妈对你买零食的总价打九折(乘以0.9)。写一个函数:

double discountPrice(double original) {  // 形参 original
    return original * 0.9;               // 九折
}

int main() {
    double myMoney = 20.0;               // 我有20元零花钱,实参
    double afterDiscount = discountPrice(myMoney); // 20 复制给 original
    cout << "打折后价格:" << afterDiscount << "元" << endl; // 输出18
    return 0;
}

例子2:考试平均分

老师让你写一个函数,计算两门课成绩的平均分。形参是 score1score2,调用时传入你的数学和语文分数。

double average(double a, double b) {     // 形参 a, b
    return (a + b) / 2.0;
}

int main() {
    double math = 95.5, chinese = 88.0; // 实参
    double avg = average(math, chinese);
    cout << "平均分 = " << avg << endl;   // 输出 91.75
    return 0;
}

新手常见的错误

❌ 错误1:形参和实参名字混用

新手容易在函数内部使用实参的变量名,以为可以自动访问外部的变量。

void add(int a, int b) {
    // 错误:函数内部不能直接使用 main() 里的变量 x 和 y,除非它们是全局变量
    // int sum = x + y;  // ❌ x 和 y 未定义
    int sum = a + b;    // ✅ 应该用形参
}

正确做法:只使用形参名字,不要幻想外部的变量名会自动传进来。

❌ 错误2:实参个数或类型不匹配

形参有3个,调用时只传2个——编译报错。或者传入一个 doubleint 形参,可能会导致精度丢失,但一般能自动转换(不过最好类型一致)。

int add(int a, int b) { return a + b; }

int main() {
    cout << add(3);        // ❌ 编译错误:缺少一个实参
    cout << add(3.5, 2.1); // ✅ 但自动转换:3.5变成3,2.1变成2,结果5(丢失小数)
    return 0;
}

❌ 错误3:以为修改形参能改变实参

就像我们前面展示的,新手可能写了这样的代码,期待 x 被修改:

void doubleValue(int n) {
    n = n * 2;   // 形参 n 被改了,但调用者的变量不变
}

int main() {
    int score = 80;
    doubleValue(score);
    cout << score;   // 仍然是 80,不是 160
    return 0;
}

如果不理解“值传递”,就会困惑。记住:形参是实参的复印件,不是原件。

❌ 错误4:函数定义时忘记写形参类型

void print(double x, y) {  // ❌ y 没有类型,编译错误
    cout << x << " " << y;
}

每个形参都必须单独声明类型,即使类型相同也不能省略。


完整可运行的示例:计算长方体的体积

下面是一个完整的程序,包含函数定义、多次调用,演示形参和实参的关系。

#include <iostream>
using namespace std;

// 计算长方体体积,形参:长、宽、高
double boxVolume(double length, double width, double height) {
    // 在函数内部,length/width/height 是形参,可以自由使用
    double volume = length * width * height;
    return volume;
}

int main() {
    // 定义三个实参(变量)
    double box1_len = 2.0;    // 长
    double box1_wid = 3.0;    // 宽
    double box1_hei = 4.0;    // 高

    // 调用函数,实参是三个变量
    double v1 = boxVolume(box1_len, box1_wid, box1_hei);
    cout << "第一个盒子体积 = " << v1 << endl;  // 输出 24

    // 直接用数字做实参
    double v2 = boxVolume(5.0, 6.0, 7.0);
    cout << "第二个盒子体积 = " << v2 << endl;  // 输出 210

    // 混合使用(变量+字面量)
    double v3 = boxVolume(box1_len, 10.0, 2.5);
    cout << "第三个盒子体积 = " << v3 << endl;  // 输出 2*10*2.5 = 50

    // 验证:形参修改不影响实参(如果我们在函数内部修改形参,不会影响外面的变量)
    // 但这里没有修改,所以没问题

    return 0;
}

运行结果:

第一个盒子体积 = 24
第二个盒子体积 = 210
第三个盒子体积 = 50

你可以看到,每次调用传进来的实参值不同,函数就用这些值做不同的计算。


相关知识点指引

  • 函数的定义和声明:形参只在函数定义中起作用。
  • 返回值:函数通过 return 把计算结果传回给调用处。
  • 变量作用域:形参是局部变量,仅在函数内部有效。
  • 引用参数:C++ 还有一种 & 引用,可以让形参直接绑定实参(不复制),此时修改形参就会修改实参——那是更高级的技巧。
  • 默认参数:可以在函数定义中给形参默认值,调用时可以不传对应实参。

明白了形参和实参,你就能写出更灵活的函数,把重复的代码“打包”起来,随时调用。动手试试吧!

例题精讲

1单选题

下列关于形参与实参的说法,正确的是( )。

A形参和实参必须同名
B形参在函数定义时就已经分配了内存空间
C实参可以是常量、变量或表达式
D在值传递中,函数内修改形参的值会影响实参
2判断题

在C++中,函数的值传递方式下,形参和实参占用不同的内存单元。

3填空题
以下程序执行后输出的结果是5。请在空白处填入一条语句,使输出结果不受影响(即仍为5)。

#include <iostream>
using namespace std;
void modify(int x) {
    ___;
}
int main() {
    int a = 5;
    modify(a);
    cout << a;
    return 0;
}
4单选题

设有函数定义:void f(int n) { n += 5; } 执行如下代码后,变量x的值是( )。 int x = 10; f(x); cout << x;

A10
B15
C20
D不确定
5判断题

在C++函数调用中,实参和形参的名称可以相同。