36人参与 • 2026-04-15 • C/C++
在学习 c++ 的过程中,初学者很容易会被这几个概念搞混:
尤其是初学者,经常会问:
int* p 和 int *p 有区别吗?& 到底是取地址还是引用?这篇文章帮你一次性彻底搞懂这些核心概念。
int a = 10; int* p = &a;
含义:
p 存的是 a 的地址*p 才是访问 a 的值可以修改指向
int b = 20; p = &b;
可以为空
int* p = nullptr;
需要解引用访问
cout << *p;
int a = 10; int& r = a;
含义:
r 就是 a 的另一个名字r = 20; // 此时 a 也变成 20
必须初始化
不能重新绑定
使用时像普通变量(不需要 *)
int a = 10; int* p = &a;
&a 表示:获取变量 a 的地址
⚠️ 注意:& 有两种用途!
int& r = a; // 定义引用 int* p = &a; // 取地址
下面用一个表格对上面的内容做一个总结:
| 特性 | 指针 | 引用 | &运算符 |
|---|---|---|---|
| 本质 | 变量 | 别名 | 操作符 |
| 是否占内存 | 是 | 是(通常实现为指针) | 否 |
| 是否可为空 | ✅ | ❌ | - |
| 是否可改变指向 | ✅ | ❌ | - |
| 使用方式 | *p | 直接用 | &a |
| 安全性 | 较低 | 更安全 | - |
在 c/c++ 中,取地址运算符
&得到的是变量在程序中的“内存地址”,但这个地址本质上是由操作系统提供的虚拟地址,而不是真实的物理内存地址;程序可以通过这个地址访问数据,但底层还需要经过操作系统和硬件(如内存管理单元)的转换才能映射到实际的物理内存。
很多人会纠结这一点,其实结论很简单:
两者完全等价,没有任何本质区别
int *p; int* p;
都表示:p 是一个指向 int 的指针,编译器处理完全一致
因为在 c++ 中:
* 实际是“修饰变量”,不是类型的一部分
看下面代码:
int* p1, p2;
实际含义是:
p1 是指针p2 是普通 int这也是很多初学者踩坑的地方
int *p1, *p2;
或者:
int* p1; int* p2;
保持风格统一最重要
| 特性 | 指针 | 引用 |
|---|---|---|
| 本质 | 存地址的变量 | 变量别名 |
| 是否可为空 | ✅ | ❌ |
| 是否可改指向 | ✅ | ❌ |
| 访问方式 | *p | 直接使用 |
| 安全性 | 较低 | 更安全 |
其中:
指针传参
void func(int* p) {
*p = 100;
}
func(&a);引用传参
void func(int& r) {
r = 100;
}
func(a);*p
通过地址来访问变量
const int* p; // 不能修改指向的值,可以修改指针本身! int* const p; // 不能修改指针本身
int&& r = 10;
&& 表示 右值引用(rvalue reference)
int a = 10; int b = a; // a 是左值 int c = 10; // 10 是右值
核心区别:
| 类型 | 特点 | |
|---|---|---|
| 左值(lvalue) | 有名字、可取地址 | |
| 右值(rvalue) | 临时值、不能取地址 |
为了解决一个核心问题:避免不必要的拷贝,提高性能
看一个例子:
std::string s1 = "hello"; std::string s2 = s1; // 拷贝(慢)
如果是临时对象(右值),它本身马上就要被销毁,如果还像普通变量一样进行拷贝,就会产生一次不必要的内存复制(比如 std::string、vector 这种内部带堆内存的数据结构),既浪费时间又浪费空间;而引入右值引用(&&)后,程序可以直接“接管”这个临时对象内部已经分配好的资源(如指针指向的内存),而不是重新申请和复制,这就是“移动语义”。右值引用的本质作用就是:针对临时对象,避免不必要的拷贝,通过资源转移来提升性能,同时保持代码安全(由对象自动管理资源)
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_ptr<int> p = std::make_unique<int>(10); // 独占所有权 std::shared_ptr<int> p1 = std::make_shared<int>(10); // 共享所有权 std::shared_ptr<int> p2 = p1; std::weak_ptr<int> wp = p1; //解决循环引用
到此这篇关于c++指针、引用与取地址运算符对比分析的文章就介绍到这了,更多相关c++指针、引用与地址运算符内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论