# 指针和引用的区别
# 简要回答
指针:是一个变量,存储另一个变量的内存地址,使用时需要引用(
*)访问目标值。可重新赋值指向其他对象,支持指针算术(如++),可为空(nullptr),指针可以有const。占用独立的内存(通常是4或8字节),需要手动管理动态内存。
引用:是变量的别名,绑定后不能修改,且不能为空,使用时无需解引用,引用没有const。
区别
不存在指向空值的引⽤,但是存在指向空值的指针
# 详细回答
# 指针
指针是存储内存地址的变量,通过声明(如int* p = &a),其值为目标对象的地址。
底层实现上,指针变量占用独立内存(32位系统4字节,64位系统8字节)。
可以重新赋值(如p = &b),支持指针算术(如p++移动地址)
可为nullptr,表示不指向有效对象,但需注意,未初始化或未判空的指针可能导致野指针,可能引发崩溃。
指针的const的修饰,其取决于const的修饰位置
- const int *p:const修饰的是指针指向的对象,不能通过指针修改对象的值,但可以改变指针本身指向的对象。
- int *const p:const修饰的是指针本身,不能改变指针指向的对象,但可以改变指针本身。
- const int *const p:const修饰的是指针指向的对象和指针本身,不能通过指针修改对象的值,也不能改变指针本身。
指针的灵活性使其在动态内存分配、数组操作、字符串处理及复杂数据结构(如链表、树)中非常有用,但需手动管理内存,否则容易造成内存泄漏。
# 引用
引用是变量的别名(如int& r = a),绑定后与目标共享内存,无独立存储空间。
编译时符号表记录引用目标的地址,绑定关系一旦建立,无法更改。
引用必须初始化且不能为空,语法上更简洁,直接操作目标变量(如r = 10)。
引用没有const修饰,但可以绑定到const对象(如const int&)。
由于引用绑定后不可更改,生命周期与绑定对象一致,无需手动管理内存,因此在函数参数传递、返回值优化等场景中更安全高效。
# 指针和引用演示
#include <iostream>
using namespace std;
int main() {
// ====== 初始化对比 ======
int a = 10;
int* ptr; // 指针可以延迟初始化
ptr = &a; // 现在指向a
ptr = nullptr; // 可以设为空指针
int& ref = a; // 引用必须初始化且不能为空
// int& ref2; // 错误:引用必须初始化
// int& ref3 = nullptr; // 错误:不能绑定到空
// ====== 重新绑定对比 ======
int b = 20;
ptr = &b; // 指针可以重新指向b
// &ref = b; // 错误:引用不能重新绑定
// ====== 内存占用对比 ======
cout << "指针大小: " << sizeof(ptr) << " bytes" << endl; // 4或8字节
cout << "引用大小: " << sizeof(ref) << " bytes" << endl; // 显示a的大小
// ====== 操作方式对比 ======
*ptr = 30; // 指针需要解引用
ref = 40; // 引用直接操作
// ====== 安全性对比 ======
if(ptr != nullptr) { // 使用指针需要判空(行29)
cout << *ptr << endl;
}
cout << ref << endl; // 引用无需判空检查(行32)
// ====== 动态内存管理 ======
int* dynPtr = new int(50); // 指针用于动态内存
cout << *dynPtr << endl;
delete dynPtr; // 必须手动释放
// 引用不能用于动态内存管理
// ====== 函数参数传递 ======
auto modifyByPtr = [](int* p) { if(p) *p += 1; };
auto modifyByRef = [](int& r) { r += 1; };
modifyByPtr(&a);
modifyByRef(a);
cout << "a = " << a << endl; // 输出42
//====== const的修饰 ======
// 引用示例
const int ci = 10;
//int& r = ci; // 错误:非const引用不能绑定到const对象
const int& cr = ci; //正确:const引用可以绑定到const对象
//指针示例
int a = 10;
const int* p1 = &a; // p1指向的值是const的
//*p1 = 20; //错误:不能通过p1修改a的值
int* const p2 = &a; // p2本身是const的,不能改变指向
//p2 = &b; //错误:不能改变p2指向的对象
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 知识拓展
指针和引用的示意图:

面试官可能追问:在实际编程中,什么情况下应该使用指针,什么情况下应该使用引用?举例子说明。
- 简答:
- 什么时候用指针? 遇到需要处理可能为NULL的情况(如可选参数时)遇到需要改变指向的对象(如遍历链表时)遇到需要动态内存分配(new/delete)遇到需要多级间接访问(如指针的指针)
- 什么时候用引用? 函数参数传递,特别是大型对象时,可以避免拷贝开销,遇到必须绑定到有效对象的场景时(如类成员引用)实现链式调用(如返回*this引用)还有运算符的重载。
← 介绍c++一下三大特性 结构体和类的区别 →
评论
验证登录状态...