C++易搞混知识: 指针、引用与取地址运算符对比分析

张开发
2026/4/10 5:52:19 15 分钟阅读

分享文章

C++易搞混知识: 指针、引用与取地址运算符对比分析
目录一、引言二、一句话快速理解三、指针Pointer1️⃣ 基本定义2️⃣ 指针的特点四、引用Reference1️⃣ 基本定义2️⃣ 使用效果3️⃣ 引用的特点五、取地址运算符 六、进阶与易错点总结6.1 int *p 和 int* p 的区别6.1.1 为什么会有两种写法6.1.2 推荐写法6.2 指针 vs 引用核心对比6.3 函数传参对比高频考点6.4 相关扩展知识6.4.1 解引用运算符 *6.4.2 常量指针6.4.3 右值引用C11 核心特性6.4.3.1 什么是右值引用6.4.3.2 左值引用 vs 右值引用6.4.3.3 为什么需要右值引用6.4.4 智能指针现代 C 必备6.4.4.1 为什么需要智能指针6.4.4.2 智能指针的本质6.4.4.3 三种常用智能指针一、引言在学习 C 的过程中初学者很容易会被这几个概念搞混指针Pointer引用Reference取地址运算符尤其是初学者经常会问int* p和int *p有区别吗到底是取地址还是引用指针和引用是不是一回事这篇文章帮你一次性彻底搞懂这些核心概念。二、一句话快速理解指针存储“地址”的变量引用变量的“别名”取地址运算符同时也用于定义引用三、指针Pointer1️⃣ 基本定义int a 10; int* p a;含义p存的是a的地址*p才是访问a的值2️⃣ 指针的特点可以修改指向int b 20; p b;可以为空int* p nullptr;需要解引用访问cout *p;四、引用Reference1️⃣ 基本定义int a 10; int r a;含义r就是a的另一个名字2️⃣ 使用效果r 20; // 此时 a 也变成 203️⃣ 引用的特点必须初始化不能重新绑定使用时像普通变量不需要*五、取地址运算符int a 10; int* p a;a表示获取变量a的地址⚠️ 注意有两种用途int r a; // 定义引用 int* p a; // 取地址下面用一个表格对上面的内容做一个总结特性指针引用运算符本质变量别名操作符是否占内存是是通常实现为指针否是否可为空✅❌-是否可改变指向✅❌-使用方式*p直接用a安全性较低更安全-在 C/C 中取地址运算符得到的是变量在程序中的“内存地址”但这个地址本质上是由操作系统提供的虚拟地址而不是真实的物理内存地址程序可以通过这个地址访问数据但底层还需要经过操作系统和硬件如内存管理单元的转换才能映射到实际的物理内存。六、进阶与易错点总结6.1int *p和int* p的区别很多人会纠结这一点其实结论很简单两者完全等价没有任何本质区别int *p; int* p;都表示p是一个指向int的指针编译器处理完全一致6.1.1 为什么会有两种写法因为在 C 中*实际是“修饰变量”不是类型的一部分看下面代码int* p1, p2;实际含义是p1是指针p2是普通int这也是很多初学者踩坑的地方6.1.2 推荐写法int *p1, *p2;或者int* p1; int* p2;保持风格统一最重要6.2 指针 vs 引用核心对比特性指针引用本质存地址的变量变量别名是否可为空✅❌是否可改指向✅❌访问方式*p直接使用安全性较低更安全其中指针更灵活但更容易出错引用更安全但限制更多6.3 函数传参对比高频考点指针传参void func(int* p) { *p 100; } func(a);引用传参void func(int r) { r 100; } func(a);6.4 相关扩展知识6.4.1 解引用运算符**p通过地址来访问变量6.4.2 常量指针const int* p; // 不能修改指向的值可以修改指针本身 int* const p; // 不能修改指针本身6.4.3 右值引用C11 核心特性6.4.3.1 什么是右值引用int r 10;表示右值引用rvalue reference6.4.3.2 左值引用 vs 右值引用int a 10; int b a; // a 是左值 int c 10; // 10 是右值核心区别类型特点左值lvalue有名字、可取地址右值rvalue临时值、不能取地址6.4.3.3 为什么需要右值引用为了解决一个核心问题避免不必要的拷贝提高性能看一个例子std::string s1 hello; std::string s2 s1; // 拷贝慢如果是临时对象右值它本身马上就要被销毁如果还像普通变量一样进行拷贝就会产生一次不必要的内存复制比如std::string、vector这种内部带堆内存的数据结构既浪费时间又浪费空间而引入右值引用后程序可以直接“接管”这个临时对象内部已经分配好的资源如指针指向的内存而不是重新申请和复制这就是“移动语义”。右值引用的本质作用就是针对临时对象避免不必要的拷贝通过资源转移来提升性能同时保持代码安全由对象自动管理资源6.4.4 智能指针现代 C 必备6.4.4.1 为什么需要智能指针传统指针的问题int* p new int(10); // 忘记 delete → 内存泄漏常见问题内存泄漏重复释放悬空指针6.4.4.2 智能指针的本质用对象管理指针RAII思想#include memory把原本需要手动new/delete的指针资源交给一个对象来负责生命周期这个对象在构造时获取资源在析构时自动释放资源从而避免内存泄漏和忘记释放的问题。6.4.4.3 三种常用智能指针std::unique_ptrint p std::make_uniqueint(10); // 独占所有权 std::shared_ptrint p1 std::make_sharedint(10); // 共享所有权 std::shared_ptrint p2 p1; std::weak_ptrint wp p1; //解决循环引用

更多文章