c++核心之万字详解 * 和 & 所有用法(指针、引用、取地址、解引用、常量修饰)

前言

在 C++ 学习过程中, * (星号) 和 & (取地址符/引用符) 是最容易混淆、也是贯穿指针、引用、函数传参、内存操作、STL 底层的核心符号。

很多初学者的痛点:

  1. 分不清 & 是取地址还是引用
  2. 分不清 * 是定义指针还是解引用
  3. const 结合 *& 后彻底看不懂修饰关系
  4. 函数传值、传指针、传引用傻傻分不清

本文全覆盖、无遗漏整理 * 和 & 的所有使用场景,搭配可运行代码、底层原理、易错点对比,彻底吃透这两个核心符号。

适用人群:C++ 入门、面试复盘、底层源码学习(STL/ROS/算法开发)

一、符号核心定位总结(先建立全局认知)

1.1 & 符号 两种核心身份

  1. 单目运算符:取地址(编译期取值,获取变量内存地址)
  2. 类型修饰符:引用(别名)(C++独有语法,C语言没有)

1.2 * 符号 两种核心身份

  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

关键特性
  1. & 不能作用于常量&10 报错,常量无内存地址
  2. & 可以取数组、结构体、对象的地址
  3. 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】迭代器底层原理剖析
 
相关推荐
Legendary_0081 小时前
解析 PD Sink 与 LDR6500U:Type-C 取电的核心密码
c语言·开发语言
冴羽yayujs1 小时前
JavaScript 9 个先有库再有 API 的故事
开发语言·javascript·ecmascript
回忆2012初秋1 小时前
.NET 8.0 实战:基于 MQTTnet 封装高可用的 MQTT 发布/订阅工具类
开发语言·mqtt·.net
油丶酸萝卜别吃1 小时前
JavaScript 深度合并函数 deepMerge 实现指南(附完整测试用例)
开发语言·javascript·测试用例
念恒123061 小时前
Python(for循环进阶)
开发语言·python
AI玫瑰助手2 小时前
Python运算符:算术运算符(加减乘除取模幂)详解
开发语言·python
xiaoye-duck2 小时前
Qt 信号与槽深度解析:connect 用法、自定义信号槽与 Lambda 实战
开发语言·qt
lsx2024062 小时前
C AI 编程助手:助力开发者高效编程
开发语言
沐知全栈开发2 小时前
Eclipse 编译项目指南
开发语言