# std::addressof

< cpp‎ | memory

定义于头文件 `<memory>` |  |
| (1) |
template< class T > T* addressof(T& arg) noexcept; |  | (C++11 起) (C++17 前)
template< class T > constexpr T* addressof(T& arg) noexcept; |  | (C++17 起)
template <class T> const T* addressof(const T&&) = delete; | (2) | (C++17 起)

1) 获得对象或函数 `arg` 的实际地址，即使存在 `operator&` 的重载
2) 右值重载被删除，以避免取 const 右值的地址。

表达式 `std::addressof(E)` 是一个常量表达式，若 `E` 是左值常量子表达式。 | (C++17 起)

### 参数

arg | - | 左值对象或函数

### 返回值

指向 `arg` 的指针。

### 可能的实现

    template<class T>
    typename std::enable_if<std::is_object<T>::value, T*>::type  addressof(T& arg) noexcept
    {
        return reinterpret_cast<T*>(
                   &const_cast<char&>(
                       reinterpret_cast<const volatile char&>(arg)));
    }

    template<class T>
    typename std::enable_if<!std::is_object<T>::value, T*>::type addressof(T& arg) noexcept
    {
        return &arg;
    }

注：上述实现不是 `constexpr` （这要求编译器支持）。

### 示例

operator& 可以为指针封装器类重载，以获得指向指针的指针：

    #include <iostream>
    #include <memory>

    template<class T>
    struct Ptr {
        T* pad; // 增加填充以显示‘ this ’和‘ data ’的区别
        T* data;
        Ptr(T* arg) : pad(nullptr), data(arg)
        {
            std::cout << "Ctor this = " << this << std::endl;
        }

        ~Ptr() { delete data; }
        T** operator&() { return &data; }
    };

    template<class T>
    void f(Ptr<T>* p)
    {
        std::cout << "Ptr   overload called with p = " << p << '\n';
    }

    void f(int** p)
    {
        std::cout << "int** overload called with p = " << p << '\n';
    }

    int main()
    {
        Ptr<int> p(new int(42));
        f(&p);                 // 调用 int** 重载
        f(std::addressof(p));  // 调用 Ptr<int>* 重载，（ = this ）
    }

可能的输出：

    Ctor this = 0x7fff59ae6e88
    int** overload called with p = 0x7fff59ae6e90
    Ptr   overload called with p = 0x7fff59ae6e88

### 参阅

allocator | 默认的分配器 (类模板)
pointer_to [静态] | 获得指向其参数的可解引用指针 (`std::pointer_traits<Ptr>` 的公开静态成员函数)