C++ 学习笔记(3):引用和指针
前言
前几天问 GPT 问的,单独拎出来当作笔记的一个补充吧。
指针的基本概念
指针(Pointer) 是一个变量,它存储的是另一个变量的内存地址。在 C++ 中,定义一个指针变量时使用 *
符号,这个符号并不是表示解引用,而是表示这个变量是一个指针变量,指向某种类型的数据。
例子
int a = 5;
int* p = &a; // p 是一个指向 a 的指针,&a 获取 a 的地址
在上面的例子中,&a
表示获取 a
的内存地址,而 int* p
表示定义一个指向 int
类型的指针变量 p
。*p
表示解引用,访问指针 p
指向的内存位置中的数据。
解引用的概念
解引用(Dereferencing) 是指通过指针访问它指向的内存地址中的内容。当你使用 *p
时,你是在访问指针 p
存储的地址所指向的数据,而不是地址本身。
例子
int a = 5;
int* p = &a; // p 存储 a 的地址
cout << *p; // 解引用 p,输出 5,因为 p 指向 a
重要概念: *p
代表解引用,访问的是指针 p
所指向内存位置中的数据,而不是 p
本身。也就是说,*p
是访问 a
的值(即 5
),而 p
只是存储了 a
的地址。
引用与指针的区别
引用(Reference) 只是某个对象的别名,通过引用,你直接操作原始对象的数据。引用变量不存储内存地址,只是对已有对象的别名,不能为 null
或空指针。
例子
int a = 5;
int& ref = a; // ref 是 a 的引用
ref = 10; // 修改 ref 的值,a 变为 10
cout << a; // 输出 10,a 被修改了
在这个例子中,ref
直接代表 a
,修改 ref
就等于修改 a
。没有像指针那样通过解引用去访问,引用的操作更直接、简洁。
常见误解:*p = &x
和 *p
的使用
我前面提到了一个问题,就是:为什么 *p = &x
不成立,而 *p
作为解引用操作并没有做到“放地址”。这实际是理解上的一个小误区。
关键点
定义指针时,*p
是用来声明指针的类型,它告诉编译器 p
是一个指向某类型(如 int
)的指针。而 &x
是取地址操作,表示你要拿到 x
变量的内存地址。
*p = &x
其实是错误的,因为 *p
不是存储地址的地方,它应该存储的是值,而不是一个地址。正确的做法是:
int x = 10;
int* p = &x; // p 存储的是 x 的地址
*p = 20; // 解引用 p,把 x 的值改成 20
cout << x; // 输出 20,x 的值被修改了
正确理解: 当你用 *p
进行解引用时,它实际上是指向 p
所指向的内存位置的内容。所以 *p
用于访问指针指向的对象的值,而不是用来放地址的。
引用与指针的比较
特性 | 引用(Reference) | 指针(Pointer) |
---|---|---|
定义时初始化 | 必须在定义时初始化,一旦初始化后无法改变。 | 可以初始化为 nullptr ,并且可以随时改变指向的对象。 |
存储内容 | 存储对象的别名,没有独立的内存地址。 | 存储的是一个内存地址,指向某个对象。 |
是否为空 | 不可以为空,引用必须绑定到一个对象。 | 可以为空(nullptr ),也可以指向不同的对象。 |
访问方式 | 直接使用引用变量名即可访问原始对象。 | 使用 * 操作符解引用来访问指针所指向的内容。 |
是否可以改变 | 一旦绑定,引用无法指向其他对象。 | 可以改变指针指向的对象,甚至指向 nullptr 。 |
适用场景 | 适用于不需要重新绑定的对象,通常用于修改对象的值。 | 适用于需要灵活指向不同对象、动态内存分配和处理链表等。 |
例子:引用和指针的操作对比
#include <iostream>
using namespace std;
void byReference(int& ref) {
ref = 10; // 通过引用修改原始值
}
void byPointer(int* p) {
*p = 20; // 通过指针解引用修改原始值
}
int main() {
int a = 5;
int b = 15;
byReference(a); // a 通过引用传递给函数,a 变为 10
byPointer(&b); // b 通过指针传递给函数,b 变为 20
cout << "a: " << a << endl; // 输出 a: 10
cout << "b: " << b << endl; // 输出 b: 20
return 0;
}
引用:直接作为别名操作数据,语法简单且无需解引用。指针:存储的是地址,需要通过解引用来访问指向的数据,使用时更灵活。
常见的使用场景
引用 常用于函数参数传递(避免传值开销),或者需要直接修改原始对象的场景。指针 常用于动态内存分配(new
和 delete
)、数据结构(链表、树)、以及需要操作多个对象或空指针的场景。
总结
指针 是一个变量,它存储了某个对象的内存地址,并且通过 *
来解引用,访问或修改指向的对象的内容。引用 是某个对象的别名,它直接代表对象本身,不需要解引用操作,操作简洁。在 定义指针时,*p
只是用来告诉编译器 p
是一个指针类型变量,而 解引用 是通过 *p
访问指针指向的内容。
这篇结束后打算直接刷题了,发现一点一点学根本没那时间我服了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)