InfoCode

C++ · 函数

函数定义与调用

逐步比较修改int副本、通过int引用修改原变量和接收函数返回值,用同一组数据检查调用后的变量变化。

InfoCode 编写 · 技术参考见下文

在应用中练这个知识点 在应用中阅读讲解

函数的输入、处理与返回

想象函数是一台自动售货机:你把钱(参数)投进去,机器按照固定程序(函数体)运作,最后吐出饮料(返回值)。每次投不同面额,就得到不同结果。

何时用?当同一段逻辑要在程序里用好几次,就把它提取成函数,避免复制粘贴。

值传递 vs 引用传递:普通参数是"复印件"——函数里改了不影响外面;加 & 的引用参数是"原件"——函数里改了外面也变。

指针参数:void update(int* p) 接收的是地址的副本,通过 *p 可以修改地址所指的对象;但直接给 p 赋另一个地址,只会改变函数内的指针副本。可用 const 引用传入只读的大对象,减少复制。定义函数还应说明参数约束、返回结果和空指针处理方式。

值传递与引用传递:追踪同一个输入

函数先接收输入,再执行函数体;有返回值时,调用者可以接收结果。下面从n=4开始:普通int参数保存一个副本,修改它不会改变调用者的n;int&参数是调用者对象的另一个名字。先预测n和result,再看执行过程。

步骤函数内发生什么调用后nresult
int n = 4;尚未调用4尚未声明
int result = byValue(n);副本4加2,返回646
byReference(n);通过引用把n加266
n = byValue(n);副本6加2,返回8后赋给n86

错误一:以为参数名和外面的变量名一样,就一定是同一个对象;判断要看声明的类型和绑定。错误二:以为调用有返回值的函数,原变量会自动更新;要保存结果,应接收返回值或显式赋值。

这里限定普通int值参数,不推广成“所有传值函数都不能改变外部状态”:指针副本仍可能指向外部对象。引用绑定后,对引用赋值是修改所绑定对象,不是换绑定。需要计算一个新结果时,返回值通常清楚;需要修改调用者对象时才选择合适的可写引用。不要返回局部变量的引用。这些固定次数整数运算是O(1),不代表所有函数或所有类型的复制都是O(1)。

运行验证:改副本、改原值、接收结果

#include <iostream>
int byValue(int value) { value += 2; return value; }
void byReference(int& value) { value += 2; }
int main() {
    int n = 4;
    int result = byValue(n);
    std::cout << n << " " << result << "\n";
    byReference(n);
    std::cout << n << " " << result << "\n";
    n = byValue(n);
    std::cout << n << " " << result << "\n";
}

输出三行4 6、6 6、8 6。result是自己保存的值,不会随n改变。

先自己判断,再展开答案

只把函数里的参数value改名为n,传值就会变成引用吗?

不会,名字不改变int与int&的传参规则;同名也可能是不同对象。

n=10,调用byValue(n)但不接收返回值,n是多少?

还是10。函数返回12,但这个结果没有写回n。

写int& alias=n; alias=9;,这是改n还是让alias改绑到9?

n变成9;alias仍引用原来的n。引用初始化后不能靠赋值换绑定。

调用、引用与参数示例

例1:计算两数之和

#include <iostream>
using namespace std;

// 定义函数:接收两个整数,返回它们的和
int add(int a, int b) {
    return a + b;
}

int main() {
    int x = 3, y = 5;
    cout << add(x, y) << endl;  // 输出 8
    cout << add(10, 20) << endl; // 输出 30
    return 0;
}

调用 add(3,5) 时,a=3、b=5 是复印件,函数返回 8;再调用 add(10,20) 时参数换成 10 和 20,函数照样运行,返回 30。

例2:用引用参数交换两个数

#include <iostream>
using namespace std;

// 引用参数:&a、&b 是原件,修改后外部也变
void swap2(int &a, int &b) {
    int tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int x = 3, y = 7;
    swap2(x, y);
    cout << x << " " << y << endl; // 输出 7 3
    return 0;
}

因为用了引用参数,函数内部对 a、b 的修改直接作用于 main 里的 x 和 y,所以输出变成了 7 3。

例3:修改所指对象与修改指针本身

#include <iostream>
using namespace std;
void update(int* p) {
    if (p != nullptr) *p += 1;
    p = nullptr; // 只改变本地指针副本
}
int main() {
    int x = 4; int* p = &x;
    update(p); update(nullptr);
    cout << x << " " << (p == &x) << endl;
}

输出 5 1。x 经解引用被修改,外面的 p 仍指向 x;函数也检查了空指针。

提示

技术参考

范围说明

本站讲解由 InfoCode 编写,不是官方考纲;参考级别是本站映射,不代表官方等级、认证或参赛资格。练习记录不等于掌握或资格。

参考级别:GESP 4 级(本站映射)

查看赛事关系与路径