第二节 · 以不变应万变 · 深入参数与返回值

在上一节中,我们初步认识了函数——一段有名字的、可重复使用的代码。现在,让我们更深入地了解函数的参数和返回值。

函数就像一台机器:你往里面放入原料(参数),它经过加工处理,产出成品(返回值)。而这台机器处理原料的方式,以及产出成品的形式,都大有讲究。


参数传递的方式

当我们调用函数时,实参的值是如何传递给形参的呢?C++ 提供了几种不同的传递方式。

值传递

这是最基本的传递方式。调用函数时,实参的值会被复制一份给形参:

void addOne(int n)
{
    n = n + 1;
    cout << "函数内 n = " << n << endl;
}

int main()
{
    int x = 10;
    addOne(x);
    cout << "函数外 x = " << x << endl;
    return 0;
}

输出结果:

为什么 x 的值没有改变?因为传递给函数的只是 x 的一个副本,函数内部修改的是这个副本,而不是 x 本身。这就像你把一份文件复印一份给别人,别人在复印件上涂改不会影响你的原件。

引用传递

如果我们希望函数能够修改实参的值,可以使用引用传递

输出结果:

在形参类型后加上 &,表示这个参数是一个引用。引用可以看作是原变量的一个别名,对引用的操作就是对原变量的操作。

指针传递

我们也可以通过传递指针来实现类似的效果:

指针传递和引用传递的效果类似,但语法上有所不同。引用在使用时更加自然,而指针更加灵活(比如可以为空、可以重新指向其他对象)。


常量引用

有时候,我们想通过引用传递来避免复制的开销,但又不希望函数修改参数的值。这时可以使用常量引用

const 关键字表示这个引用是只读的,函数内部不能通过它修改原变量。这样既避免了复制的开销,又保证了数据的安全。

对于基本类型(如 intdouble),值传递的开销很小,通常直接用值传递即可。但对于较大的对象(如 stringvector),使用常量引用可以显著提高效率。


返回值

函数可以返回一个值给调用者。返回值的类型在函数声明时指定:

如果函数不需要返回任何值,可以将返回类型声明为 void

返回引用

函数也可以返回引用:

返回引用时要特别注意:不要返回局部变量的引用,因为局部变量在函数结束后就会被销毁:


多个返回值

C++ 的函数只能返回一个值,但如果我们需要返回多个值怎么办?

方法一:使用引用参数

方法二:返回结构体或类

方法三:使用 pair 或 tuple(C++11)


数组作为参数

数组名在传递给函数时,实际上传递的是数组首元素的指针。因此,函数内部无法知道数组的长度,需要额外传递一个参数:

以下三种声明方式是等价的:


理解参数传递和返回值的机制,对于编写高效、正确的程序至关重要。在实际编程中,我们需要根据具体情况选择合适的传递方式。

习题

  • 编写一个函数 swap,交换两个整数的值。分别使用引用和指针两种方式实现。

  • 编写一个函数,接收一个整数数组,返回数组中的最大值和最小值。

Last updated