MST

星途 面试题库

面试题:C++ 中值传递与引用传递在函数调用开销上的差异

在 C++ 中,简述值传递和引用传递在函数调用时,对于开销方面的不同表现,并举例说明什么时候选择值传递更好,什么时候选择引用传递更好。
27.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

值传递和引用传递在开销方面的不同表现

  • 值传递
    • 当函数参数采用值传递时,会在栈上为形参分配内存空间,并将实参的值拷贝到形参的内存空间中。如果传递的是较大的对象,这种拷贝操作会带来较大的开销,包括时间开销(执行拷贝操作的时间)和空间开销(为形参额外分配的内存空间)。
    • 例如,传递一个包含大量成员变量的自定义结构体或类对象时,拷贝操作会比较耗时和占用额外空间。
  • 引用传递
    • 引用传递本质上传递的是实参的地址,在函数调用时,形参只是实参的一个别名,不会为形参重新分配内存空间,也不需要进行拷贝操作。因此,引用传递在传递较大对象时,时间和空间开销都比值传递小很多。

选择值传递更好的情况

  • 传递基本数据类型(如 int、char、double 等):因为基本数据类型的大小通常较小,拷贝操作的开销不大,使用值传递简单直观,代码可读性好。例如:
void increment(int num) {
    num++;
}
int main() {
    int a = 5;
    increment(a);
    return 0;
}

这里传递 int 类型的变量 a,值传递简单高效。

  • 需要对参数进行独立修改,不影响实参:当函数需要对传入的参数进行修改,并且希望这种修改不影响调用函数中的实参时,值传递是合适的选择。例如,在排序算法的实现中,如果函数只是对局部的数组副本进行排序而不改变原始数组,使用值传递传递数组参数是可以的(虽然在 C++ 中数组作为参数传递时会退化为指针,但原理类似)。

选择引用传递更好的情况

  • 传递大对象(自定义结构体或类对象):为了避免大对象拷贝带来的高开销,使用引用传递可以显著提高效率。例如:
class BigObject {
public:
    int data[1000];
};
void processObject(BigObject& obj) {
    // 处理对象
}
int main() {
    BigObject bigObj;
    processObject(bigObj);
    return 0;
}

这里传递 BigObject 类型的对象 bigObj,通过引用传递避免了大对象的拷贝。

  • 希望函数能修改实参:当函数需要修改调用函数中的实参值时,引用传递是必须的。例如,交换两个变量值的函数:
void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}
int main() {
    int x = 3, y = 5;
    swap(x, y);
    return 0;
}

通过引用传递,函数 swap 可以直接修改调用函数中的变量 xy 的值。