面试题答案
一键面试引用和指针作为函数参数传递的特点及本质差异
-
引用:
- 特点:
- 引用必须在定义时初始化,之后不能再引用其他对象,它是对象的别名。
- 使用引用作为函数参数传递时,在函数内部对引用的操作就是对原对象的操作,语法上更简洁直观,无需像指针那样通过解引用操作符(
*
)来访问对象。 - 引用不能为空,保证了对对象的有效访问。
- 本质差异:引用在底层实现上可能是通过指针来实现的,但在使用层面,它的语法更像对象本身,而不是一个存储地址的变量。引用一旦初始化,其指向不可改变。
- 特点:
-
指针:
- 特点:
- 指针是一个变量,存储的是另一个变量的地址。它可以在运行时改变指向不同的对象,灵活性更高。
- 使用指针作为函数参数传递时,需要通过解引用操作符(
*
)来访问指针所指向的对象。 - 指针可以为空(
nullptr
),这在某些情况下可以用来表示特殊的状态。
- 本质差异:指针本身是一个变量,有自己的内存空间,存储的是所指向对象的地址。它可以动态地改变指向,这是与引用的重要区别。
- 特点:
代码示例及适用场景
- 适合使用引用传递参数的场景: 当函数需要修改传入对象的值,且该对象必定存在且不需要动态改变指向时,适合使用引用。例如,实现一个交换两个整数的函数:
#include <iostream>
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int num1 = 5;
int num2 = 10;
swap(num1, num2);
std::cout << "num1: " << num1 << ", num2: " << num2 << std::endl;
return 0;
}
在这个场景中,swap
函数通过引用直接操作传入的变量,语法简洁明了,且确保了操作的是有效的对象。
- 适合使用指针传递参数的场景: 当函数需要处理对象是否存在的情况,或者需要动态改变指针的指向时,适合使用指针。例如,实现一个释放动态分配内存的函数,且指针可能为空:
#include <iostream>
#include <cstdlib>
void freeMemory(int*& ptr) {
if (ptr != nullptr) {
std::free(ptr);
ptr = nullptr;
}
}
int main() {
int* numPtr = static_cast<int*>(std::malloc(sizeof(int)));
if (numPtr) {
*numPtr = 42;
std::cout << "Before free: " << *numPtr << std::endl;
freeMemory(numPtr);
if (numPtr == nullptr) {
std::cout << "Memory freed, ptr is nullptr." << std::endl;
}
}
return 0;
}
在这个场景中,freeMemory
函数可以处理指针为空的情况,并且通过指针的引用(int*&
)可以在函数内部改变指针的指向,将其设为nullptr
。如果使用引用,就无法处理传入对象不存在(空指针)的情况。