MST

星途 面试题库

面试题:C++ 中引用与指针在性能方面的基础差异

简述 C++ 中引用与指针在一般使用场景下性能的主要差异,并举例说明在哪些情况下这种差异会比较明显。
28.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 性能差异
    • 引用
      • 引用在本质上是一个“别名”,编译器在编译阶段会将引用替换为被引用对象的地址,在使用上它像对象本身一样直接操作,没有额外的间接寻址开销。
      • 引用一旦初始化后不能再改变指向,在使用过程中编译器可以更好地进行优化,生成更紧凑的代码。
    • 指针
      • 指针存储的是对象的地址,在访问指针所指向的对象时,需要通过间接寻址操作(解引用 * 运算符)来获取对象。这会带来一定的额外开销,尤其是在频繁解引用的情况下。
      • 指针的值可以在运行时改变,指向不同的对象,这增加了程序的灵活性,但也使得编译器较难进行某些优化,因为它需要考虑指针指向的不确定性。
  2. 差异明显的情况举例
    • 循环中频繁访问对象
      • 使用引用
#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    int& ref = numbers[0];
    for (size_t i = 0; i < numbers.size(); ++i) {
        ref = numbers[i];
        std::cout << ref << " ";
    }
    return 0;
}

在这个例子中,ref 作为 numbers[0] 的引用,在循环中直接访问和修改 numbers 中的元素,没有额外的间接寻址开销。 - 使用指针

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    int* ptr = &numbers[0];
    for (size_t i = 0; i < numbers.size(); ++i) {
        *ptr = numbers[i];
        std::cout << *ptr << " ";
        ptr++;
    }
    return 0;
}

这里使用指针 ptr,每次访问和修改元素都需要解引用操作 *ptr,产生额外开销,尤其是在大数据量的循环中,这种开销会更加明显。

  • 函数参数传递
    • 引用作为参数
#include <iostream>

void modifyValue(int& value) {
    value++;
}

int main() {
    int num = 5;
    modifyValue(num);
    std::cout << num << std::endl;
    return 0;
}

引用作为函数参数传递时,编译器可以直接对传入的对象进行操作,没有额外的地址传递开销。 - 指针作为参数

#include <iostream>

void modifyValue(int* value) {
    (*value)++;
}

int main() {
    int num = 5;
    modifyValue(&num);
    std::cout << num << std::endl;
    return 0;
}

指针作为参数传递时,需要先传递指针的值(即地址),在函数内部再通过解引用操作来访问和修改对象,相比引用多了间接寻址的过程,在频繁调用这种函数时性能差异会体现出来。