前言
在 C++ 学习过程中, * (星号) 和 & (取地址符/引用符) 是最容易混淆、也是贯穿指针、引用、函数传参、内存操作、STL 底层的核心符号。
很多初学者的痛点:
- 分不清 & 是取地址还是引用
- 分不清 * 是定义指针还是解引用
- const 结合 *& 后彻底看不懂修饰关系
- 函数传值、传指针、传引用傻傻分不清
本文全覆盖、无遗漏整理 * 和 & 的所有使用场景,搭配可运行代码、底层原理、易错点对比,彻底吃透这两个核心符号。
适用人群:C++ 入门、面试复盘、底层源码学习(STL/ROS/算法开发)
一、符号核心定位总结(先建立全局认知)
1.1 & 符号 两种核心身份
- 单目运算符:取地址(编译期取值,获取变量内存地址)
- 类型修饰符:引用(别名)(C++独有语法,C语言没有)
1.2 * 符号 两种核心身份
- 类型修饰符:定义指针变量(修饰变量类型,表示该变量存内存地址)
- 单目运算符:解引用(通过指针地址,访问地址对应的内存数据)
核心口诀:
定义变量时是类型修饰,使用变量时是运算操作
二、& 符号 完整用法详解
2.1 用法一:单目运算符 ------ 取地址操作
功能
获取普通变量、数组、对象的内存首地址,返回地址值(十六进制/十进制内存地址)。
语法格式
cpp
变量地址 = &变量名;
完整示例 using namespace std;int main()
{
int a = 10;
// &a:取出变量a的内存地址
cout< "变量a的值:< endl;< "变量a的地址:" << endl;
return 0;
}
plaintext
运行结果
变量a的值:10
变量a的地址:0x61ff08 (地址每次运行随机变化)
plaintext
关键特性
&不能作用于常量 :&10报错,常量无内存地址&可以取数组、结构体、对象的地址- C / C++ 通用语法
2.2 用法二:类型修饰符 ------ 引用(变量别名)【C++专属】
引用是 为已有变量起别名 ,引用和原变量共用同一块内存空间,完全等价。
基础语法
cpp
数据类型 &别名 = 原变量;
核心特性(必考)
1. 引用必须初始化,不能空定义
2. 引用不可二次绑定,一旦绑定终身不变
3. 无内存开销,只是变量别名,不是新变量
4. 修改引用 = 修改原变量
基础示例
cpp
#include<iostream>
using namespace std;
int main()
{
int a = 10;
// b是a的引用(别名)
int &b = a;< "a< endl< "b = " << b << endl;
// 修改引用b,原变量a同步变化
b = 20;
< "修改后 a< endl;
// 地址完全一致
cout << "a的地址:"< endl;< "b< &< endl;
return 0;
}
运行结果
plaintext
a = 10
b = 10
修改后 a = 20
a的地址:0x61ff08
b的地址:0x61ff08
2.3 引用经典场景1:函数传引用(替代指针,最常用)
C++ 为了解决 C 语言指针传参繁琐的问题,推出引用传参,可直接修改实参,且代码更简洁。
传值 vs 传引用 对比
cpp
#include<iostream>
using namespace std;
// 传值:拷贝变量,无法修改实参
void swap1(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
// 传引用:直接操作实参内存
void swap2(int &x, int &y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int a = 10, b = 20;
swap1(a, b);
cout< "传值交换:< ",< endl; // 无变化
swap2(a, b< "传引用交换:a="< ", b="< endl; // 交换成功
return 0;
}
核心优势
1. 无需内存拷贝,效率极高(适合大对象、结构体传参)
2. 代码比指针传参更简洁、安全
3. STL 容器、ROS 函数、深度学习 C++ 接口全部默认传引用
2.4 引用经典场景2:const 常引用(只读引用)
高频面试考点,用于:接收常量、禁止修改原变量、提升大参数传参效率。
语法
cpp
const 数据类型 &别名 = 原变量;
特性
1. 可以绑定普通变量、常量、表达式、临时值
2. 无法通过引用修改数据(只读)
3. 函数传参最优解: const Type&
示例
cpp
<iostream>
using namespace std;
void print(const int &val)
{
// val = 100; 报错!常引用不可修改
cout << val << endl;
}
int main()
{
int a = 10;
const int &b = a;
print(20); // 常引用可接收临时常量
return 0;
}
2.5 右值引用 &&(拓展:C++11新特性)
简单区分:
1. & 左值引用:绑定有名字、有内存的变量
2. && 右值引用:绑定临时值、匿名值(用于移动语义、完美转发)
本文主打基础用法,面试初级阶段掌握普通左值引用即可。
三、* 符号 完整用法详解
3.1 用法一:类型修饰符 ------ 定义指针变量
指针变量:专门存放内存地址的变量。
语法
cpp
数据类型 *指针变量名;
示例
cpp
int a = 10;
// p是指针变量,存储a的地址
int *p = &a;
易错点(90%初学者踩坑)
cpp
// 错误写法误区!
int* p1, p2;
// 等价于 int *p1; int p2;
// p1是指针,p2是普通int变量!
// 正确写法
int *p1, *p2;
3.2 用法二:单目运算符 ------ 解引用操作 *指针
功能
通过指针存储的地址,访问、修改该地址对应的真实数据。
示例
cpp
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int *p = &a; // 取地址赋值给指针
cout< "指针p存储的地址:" << p << endl;
cout << "解引用*p获取< *p< endl;
// 通过指针修改原变量
*p = 100;
cout< "修改后a =< endl;
return 0;
}
运行结果
plaintext
指针p存储的地址:0x61ff08
解引用*p获取的值:10
修改后a = 100
核心总结
- p :指针本身,存地址
- *p :指针解引用,存地址对应的数据
3.3 指针与 const 组合(超级高频面试)
四种组合,彻底吃透常量指针、指针常量:
1. 常量指针: const int *p
- 指针指向的值不可改
- 指针本身的地址可以改
cpp
const int *p = &a;
// *p = 100; 报错
p = &b; // 合法
2. 指针常量: int *const p
- 指针本身地址不可改
- 指向的值可以改
cpp
int *const p = &a;
*p = 100; // 合法
// p = &b; 报错
3. 完全常量: const int *const p
- 地址、值都不可修改(只读指针)
记忆口诀
const 修饰谁,谁就不可变
- const 在 * 前:值不变
- const 在 * 后:地址不变
四、* 和 & 组合使用(工程最常用)
4.1 指针引用 int *&p
含义:给指针变量本身起别名,指针的引用
场景
函数内部修改实参指针的指向,无需二级指针。
示例
cpp
<iostream>
using namespace std;
// 指针引用:修改外部指针指向
void changePtr(int *&p)
{
static int b = 999;
p = &b;
}
int main()
{
int a = 10;
int *p = &a;
changePtr(p);
cout << endl; // 输出999
return 0;
}
4.2 取地址+解引用 抵消
*&a 等价于 a
- &a 取地址 → * 解引用还原数据
- 工程代码中常见,用于万能匹配参数类型
五、& 引用 VS * 指针 终极对比(面试必背)
特性 指针 * 引用 &
定义 存储变量地址的变量 变量的别名
内存开销 占用4/8字节(存储地址) 无内存开销
是否可空 可以为空指针 不允许空引用
是否可二次赋值 可以改变指向 不可二次绑定
使用风险 野指针、越界风险高 安全,无野引用
C语言支持 支持 不支持(C++独有)
传参效率 高 最高
工程使用准则
1. 普通传参、修改实参:优先用引用 &
2. **需要动态指向、数组操作、底层内存操作:用指针 ***
3. 大对象传参:固定用 const Type&
六、全网最全符号区分速查表
1. &变量 → 取地址(运算符)
2. 类型& 变量 → 引用别名(类型修饰)
3. 类型* 变量 → 定义指针(类型修饰)
4. *指针变量 → 解引用取值(运算符)
5. const 类型& → 常引用传参
6. 类型*& → 指针引用
七、常见报错与避坑总结
1. 引用必须初始化: int &a; 直接报错
2. 指针未初始化不可解引用:野指针崩溃
3. 连续定义指针不要写错: int *a,b 只有a是指针
4. 常引用不能修改数据
5. 引用不能绑定临时变量(普通引用)
结尾
* 和 & 是 C++ 区别于 C 语言的核心分水岭,也是指针、引用、STL、内存模型、后端/机器人/算法开发的基础。
彻底吃透这两个符号,后续学习:智能指针、迭代器、函数对象、ROS接口、深度学习C++推理 会毫无阻力。
博主往期优质干货
- 【C++】const 所有用法详解
- 【C++】指针、数组指针、函数指针精讲
- 【C++ STL】迭代器底层原理剖析