std::addressof用于获取对象真实内存地址,绕过被重载的operator&;它通过reinterpret_cast等强制取址,仅适用于左值,常见于重载取址符的类型、泛型内存操作及allocator_traits::address等场景。

std::addressof 用来获取对象真实地址,绕过被重载的 operator&
当你对一个类型调用 &obj,如果它重载了 operator&,编译器就真的会调用那个重载函数——哪怕你只想拿内存地址。这在智能指针、容器内部、或需要做底层指针操作(比如 placement new、std::allocator::address)时很危险。std::addressof 就是专治这个:它用模板和 reinterpret_cast 绕过重载,强制返回对象在内存中的起始地址。
什么时候必须用 std::addressof 而不是 &
常见于以下场景:
- 自定义类型重载了
operator&(比如某些 RAII 封装类、调试代理类) - 写泛型代码(如容器实现、内存分配器),不能假设用户类型是否重载了取址符
- 调用
std::allocator_traits::address,其默认实现内部就用了std::addressof - 手动调用
placement new前,确保传入的是原始地址而非重载函数返回值
std::addressof 的行为和限制
它不抛异常,要求参数是左值;对右值(如临时对象)调用是非法的(编译失败)。它的实现本质是:
template<class T>
constexpr T* addressof(T& arg) noexcept {
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char&>(arg))
);
}关键点:
立即学习“C++免费学习笔记(深入)”;
- 它不依赖
operator&,所以不怕被重载 - 不支持
const volatile以外的 cv 限定组合(但通常不影响使用) - 对
std::vector<int>::iterator</int>这类迭代器类型也安全——只要它是可取址的左值 - 不能用于位域成员(
struct { int x : 4; }; &s.x本身就不合法,std::addressof同样不行)
容易踩的坑:别在不该用的地方硬套
最常见的误用是把它当成“更安全的 &”到处用,其实没必要:
- 普通 POD 类型、标准容器元素、没重载
operator&的类,直接用&更清晰、无额外开销 - 对
std::unique_ptr<t></t>或std::shared_ptr<t></t>调用std::addressof(ptr),得到的是智能指针对象本身的地址,不是它指向的T*—— 别和ptr.get()搞混 - 宏或模板中盲目包裹
std::addressof(x),可能掩盖本该暴露的重载意图(比如某类故意重载operator&来禁用取址,这时用std::addressof就破坏了设计契约)
真正需要它的地方不多,但一旦需要,漏掉就会导致诡异的地址错乱或未定义行为——尤其是跨库协作或写底层设施时,没人会提醒你那个 & 已经被悄悄劫持了。










