c++中&和的含义取决于上下文:声明中是指针类型修饰符,表达式中&是取地址运算符;函数参数中&表示引用;&a类型为t,p类型为t;二者均有严格使用前提。

看位置:声明语句里 * 是指针类型修饰符,表达式里 & 是取地址
关键不是符号本身,而是它出现在哪。在变量声明中出现的 *(比如 int *p;)属于类型系统的一部分,表示“p 是一个指向 int 的指针”,此时它不执行任何运行时操作;而表达式中单独使用的 &a,才是真正的取地址运算——编译器会生成指令去读取变量 a 在栈或堆上的内存地址。
常见错误现象:
-
int *p = &5;报错:字面量5不是左值,无法取地址 -
int *p; *p = 10;崩溃:未初始化的指针解引用,访问非法内存 -
int a = 10; int &r = &a;编译失败:&a是int*类型,不能绑定到int&
看上下文:& 在函数参数里大概率是引用,不是取地址
C++ 中 & 的身份完全由上下文决定。函数形参列表里的 & 几乎总是引用声明符,和取地址无关。例如 void f(int &x) 中的 & 表示 x 是传入实参的别名,不是“把实参地址传进来”。
使用场景对比:
- 调用
f(a)时,a本身不取地址,x直接映射到a的内存位置 - 而
void g(int *p)要求显式传地址:g(&a),这里&a才是取地址运算 - 引用声明必须初始化:
int &r;单独写会编译报错
看类型:&a 的类型是 T*,*p 的类型是 T
这是最硬的区分依据。对一个 int a 变量:
-
&a的类型是int*(指针类型),可以赋给int*变量 -
*p(当p是int*)的类型是int(值类型),能参与算术运算 -
decltype(&a)是int*,decltype(*p)是int - 混淆常发生在
auto p = &a;和auto x = *p;:前者推导出指针类型,后者推导出值类型
容易踩的坑:把 & 当成“总能取地址”,把 * 当成“总能解引用”
这两个运算符都有严格前提,忽略就 crash 或未定义行为。
-
&只能作用于左值:不能对5、a + b、临时对象(如func()返回值)取地址 -
*解引用前必须确保指针非空且有效:空指针、野指针、已释放内存的指针,一解引用就崩 - 数组名是个特例:
int arr[3];中arr本身隐式转为&arr[0],但&arr类型是int(*)[3](指向整个数组的指针),和&arr[0]数值相同、类型不同
真正难的不是记规则,是在复杂表达式里快速判断当前 & 或 * 是类型修饰还是运行时运算——多看类型推导结果,比背口诀管用。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











