std::addressof不能用&代替,因为&可能被重载而返回非物理地址,而std::addressof通过reinterpret_cast绕过重载,确保获取对象内存起始地址。

std::addressof 为什么不能直接用 & 运算符代替
因为 operator& 可能被重载,而你真正想拿的是对象在内存中的物理地址。比如自定义类重载了 & 返回空指针、代理地址,甚至抛异常——这时 &obj 不再可靠。std::addressof 绕过重载,通过 reinterpret_cast 和 char& 强制取址,保证拿到的是对象起始字节的真实地址。
std::addressof 的典型使用场景
主要出现在需要绕过重载的底层操作中:
- 智能指针(如
std::unique_ptr)内部构造时确保持有真实地址 - 容器(如
std::vector)在 placement new 前获取原始内存位置 - 序列化/反射库中需跳过用户定义的
operator& - 编写通用内存拷贝或对齐检查工具时,避免被重载干扰
std::addressof 的参数限制和常见误用
std::addressof 只接受左值引用,不能传右值或临时对象:
- ✅ 正确:
int x = 42; auto p = std::addressof(x); - ❌ 错误:
auto p = std::addressof(42);—— 编译失败,42是右值 - ❌ 错误:
auto p = std::addressof(std::string("hi"));—— 同样是右值,即使加括号也不行 - ⚠️ 注意:
std::addressof对const或volatile限定符保持原样,返回类型与参数 cv-qualifier 一致
std::addressof 在 C++11 之后的兼容性细节
C++11 引入 std::addressof,但实现细节有演进:
- C++11 到 C++17:标准要求它必须“不调用
operator&”,主流实现都用reinterpret_cast<t>(reinterpret_cast<char>(t))</char></t>方式 - C++20 起允许编译器内建优化,某些情况下可被常量折叠(但行为不变)
- 不要手动模仿其实现——比如写
reinterpret_cast<t>(&t)</t>是未定义行为(违反 strict aliasing),而std::addressof是特例豁免 - 头文件只需包含
<memory></memory>(C++11 起)或<type_traits></type_traits>(部分旧库),但推荐统一用<memory></memory>
真实地址不是靠猜出来的,是靠绕过重载才拿到的;一旦你写了 operator&,就默认放弃了“取址即真实地址”的契约——这时候 std::addressof 就不是备选方案,而是唯一选择。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











