电话
400 9058 355
指针可为空,引用必须绑定有效对象;指针是存储地址的变量,引用是对象别名且声明时必须初始化,不可重绑定,无独立内存空间,不支持算术运算,sizeof引用等于所引类型大小。
这是最常被忽略的底层差异:指针变量本

nullptr 是合法值;而引用在 C++ 标准中被定义为“对象的别名”,编译器要求它在声明时就必须用一个已存在的、可取地址的对象初始化,且之后不能重绑定。
常见错误现象:int& r = *static_cast 看似只是解引用空指针,实际会触发未定义行为(UB),不是“引用为空”,而是根本没成功构造出引用——这行代码在大多数编译器下会直接崩溃或产生不可预测结果。
实操建议:
const int& 接收只读大对象(避免拷贝),但前提是调用方传入的是左值或能绑定的右值(如临时对象)const int* 或 std::optional,不能用引用加判空逻辑(引用无法判空)指针变量本身是一个对象,占用 4 或 8 字节(取决于平台),有自己的地址(&p 有意义);而引用在绝大多数编译器实现中是符号级别的别名,不分配额外栈空间——&r 返回的是它所引用对象的地址,不是“引用自身的地址”。
但注意:这不是语言标准保证。标准只要求引用的行为等价于别名,不规定是否占空间。某些特殊场景(如作为结构体成员、对引用取地址再转成指针)可能迫使编译器为其分配空间(例如 struct S { int& r; }; 在 GCC 中 sizeof(S) 可能为 8),但这属于实现细节,不应依赖。
性能影响:
*p),但现代 CPU 的缓存和预测机制下,差别微乎其微int* p = &a; p++; 合法,int& r = a; r++; 是对 a 自增,但 r++ 本身不能改变绑定目标。引用没有“++”、“+=”这类重定向操作符。
这意味着:
int* iter = arr; while (iter != end) { ... ++iter; })Base* p = new Derived; p->func();)依赖指针/智能指针,引用虽可绑定派生类对象,但无法在运行时切换目标int& get() { return data; })是安全的,只要返回的是静态存储期或调用者生命周期更长的对象;返回局部变量的引用(int& bad() { int x=0; return x; })是典型悬垂引用,UB很多候选人说“引用就是不能改指向的指针”,这种类比在理解上方便,但在底层机制和语言规则上完全错误。引用不是语法糖封装的指针,它不持有地址、不参与地址计算、不支持 reinterpret_cast 转换为其他类型指针(而 int* 可以强转为 char* 做字节操作)。
容易被忽略的关键点:
sizeof(int&) 永远等于 sizeof(int),不是指针大小template struct is_ptr : std::false_type {}; template struct is_ptr : std::true_type {}; 对引用无效)&r 显示的是目标地址,不是引用自身地址(因为它通常不存在)真正要深挖底层,得看汇编输出:g++ -S -O2 下对比 void f(int& r) { r = 42; } 和 void f(int* p) { *p = 42; } —— 你会发现它们生成的指令往往一模一样。区别不在运行时,而在编译期约束和语义表达力。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...