取地址运算符&要求操作数为具有确定内存位置的左值;右值(如字面量、临时对象、寄存器优化变量)不可取地址,否则编译失败。std::addressof可绕过operator&重载获取真实地址,适用于可疑类型。

用 & 取地址时,变量必须有确定的内存位置
不是所有“能写出来的变量”都能取地址。比如函数返回的临时对象、字面量、寄存器优化掉的局部变量(极少见但可能),& 会直接编译失败。
常见错误现象:error: lvalue required as unary '&' operand —— 说明你试图对一个右值(如 5、x + y、func() 返回的非引用类型)取地址。
- 能安全取地址的:命名变量(
int x = 42;→&x)、数组元素(&arr[0])、类成员(&obj.member) - 不能取地址的:
&42、&(x + y)、&std::string("hello")(除非绑定到 const 引用再取) - 注意 const 引用延长生命周期后,临时对象才获得地址:
const std::string& s = "hello"; &s是合法的,但&"hello"本身不行
& 和 std::addressof 的区别在哪
& 是运算符,会触发重载;std::addressof 是标准库函数,绕过重载,拿到真实地址。绝大多数情况用 & 就够了,但遇到重载了 operator& 的类(比如某些智能指针或调试代理类),& 可能返回假地址或抛异常。
- 普通类/内置类型:用
&var,简洁且高效 - 不确定是否重载了
operator&的类型(尤其第三方库中的类):优先用std::addressof(var) - 性能影响:
std::addressof是 constexpr 函数,无运行时开销,但多一次函数调用语法
示例:struct Bad { int* operator&() { return nullptr; } }; Bad b; &b 返回 nullptr,而 std::addressof(b) 才是真实地址。
立即学习“C++免费学习笔记(深入)”;
取地址后怎么避免悬垂指针
地址本身不保活,只记录位置。一旦原变量生命周期结束,指针就变悬垂,解引用必未定义行为。
- 局部变量地址不要逃逸出作用域:
int* bad() { int x = 1; return &x; }—— 绝对禁止 - 返回局部数组地址同理:
char* bad2() { char buf[10]; return buf; } - 安全做法:地址只在变量有效期内使用;传参时用引用或 const 引用代替裸指针;动态分配用智能指针管理生命周期
- 编译器警告可辅助识别:开启
-Wreturn-stack-address(GCC/Clang)
打印地址别用 %d 或 std::cout 直接输出
指针值是地址,不是整数。用错格式符会导致截断、符号扩展或平台不兼容(比如 64 位地址被当 32 位打印)。
- 正确方式一(C 风格):
printf("%p", (void*)&x);—— 必须转void*,否则未定义 - 正确方式二(C++ 风格):
std::cout (&x); - 错误示范:
printf("%lu", &x)(类型不匹配)、std::cout (可能触发 operator<li>调试时想看十六进制数值?确保类型是 <code>void*,否则输出不可靠
真正容易被忽略的是:地址打印只是调试手段,它不解决生命周期问题,也不代表你能安全访问那块内存——地址存在 ≠ 内存可用。










