GESP C++ 4 级 · 知识点

函数参数传递的概念

GESP C++ 四级要求理解值传递与引用传递的区别,知道怎样在函数内修改调用者的变量。交换两个数为什么没生效,是这一节最经典的问题。

对应知识域:函数参数传递的概念相关真题 4 套

本页为本站原创整理,例题与解析均由本站编写,不取自任何题库原题;考试范围以 CCF 官方公布为准,本平台不是 GESP 官方平台。

考纲要求

  • 理解值传递是把实参的值复制给形参,函数内修改形参不影响实参。
  • 掌握引用参数的写法,例如 int &x,函数内对它的修改会直接作用到实参。
  • 能根据需求选择传递方式:只读计算用值传递,需要修改用引用传递。
  • 知道数组作为参数传递时传递的是首地址,函数内修改元素会影响原数组。

典型题型

  • 给出函数与调用,要求写出调用后变量的值。
  • 把值传递函数改成引用传递,以满足修改实参的需求。
  • 分析交换两个数的函数为什么没有生效。

常见错误

  • 写 swap 时用值传递,函数内交换了形参,调用处的两个数没有任何变化。
  • 以为引用传递会多复制一份数据,实际上形参与实参是同一个对象。
  • 对不需要修改的参数也使用引用,增加误改风险。
  • 把数组参数写成 int a[10] 并以为长度信息也被传入,实际长度需要另外传。

深入理解

值传递改不动外面

默认的参数传递是值传递:把实参的值复制给形参,函数里操作的是副本。所以这个经典写法不会交换成功:

void swap(int a, int b) { int t = a; a = b; b = t; }
int x = 1, y = 2;
swap(x, y);        // x 仍是 1,y 仍是 2

函数里确实交换了,但交换的是 a 和 b 这两个副本,函数一结束它们就消失了,外面的 x、y 从头到尾没被碰过。这是四级最高频的判断题。

加一个 & 就变成引用传递

把形参写成 int &a,a 就成了实参的别名,不是副本。对 a 做的任何修改都会直接作用到外面的变量上:

void swap(int &a, int &b) { int t = a; a = b; b = t; }
swap(x, y);        // 这次交换成功

「引用」在 C++ 里就是给已有变量起第二个名字,因此它必须在定义时绑定,不能先声明再绑定,也不能绑到常量上(除非加 const)。除了修改实参,引用还常用于避免大对象拷贝,例如传 string 或结构体时写成 const T &,既快又不会改到原值。

数组名传参是另一套规则

把数组传给函数时,传的不是整个数组,而是首元素的地址,所以函数里对数组元素的修改会真正影响到外面。正因为只传了地址,函数不知道数组有多长,必须额外传一个长度参数:

void fill(int a[], int n) {
    for (int i = 0; i < n; i++) a[i] = 0;
}

int a[] 和 int *a 在形参位置完全等价。这也解释了 sizeof(a) 在函数里得到的是指针大小而不是数组大小——这是很多人第一次遇到时想不通的地方。

自编例题

为什么值传递的交换不生效

比较下面两个交换函数的效果。

void badSwap(int a, int b) { int t = a; a = b; b = t; }
void goodSwap(int &a, int &b) { int t = a; a = b; b = t; }
int x = 1, y = 2;
badSwap(x, y);   // x = 1, y = 2
goodSwap(x, y);  // x = 2, y = 1

badSwap 接收的是 x 和 y 的副本,函数内交换的只是形参 a 和 b,函数结束后副本被丢弃,x 与 y 保持原值。goodSwap 的形参是引用,a 和 b 分别绑定到 x 和 y 本身,函数内对它们的修改就是对外部变量的修改,所以交换生效。值传递传递的是值,引用传递传递的是同一个对象。考试里判断能否修改实参,看形参有没有加引用符号即可。

相关真题

这块内容在整条路线里的位置:GESP C++ 4 级备考路径。

READY TO START

开始练习

先做一套本级别测评,报告会指出哪些知识点需要重点补;再回到本页对照考纲要求逐条核对,把不确定的条目记下来集中练。

常见问题

引用参数和指针参数有什么区别?

引用参数写法更简单,使用时像普通变量,不能为空;指针参数需要解引用,可以为空指针,灵活性更高但更易出错。

字符串传参复制开销大吗?

值传递会复制整个字符串,内容长时开销明显。只读访问应使用 const string & 避免复制。

传数组时长度怎么处理?

数组名传参只传首地址,函数内拿不到长度,必须额外传一个长度参数,或者约定结束标记。

本级别其他知识点

官方依据