std::to_address

来自cppreference.com
< cpp‎ | memory
 
 
 
动态内存管理
未初始化存储
(C++17)
垃圾收集支持
杂项
to_address
(C++20)
(C++11)
(C++11)
C 库
低层内存管理
 
定义于头文件 <memory>
template< class Ptr >
auto to_address(const Ptr& p) noexcept;
(1) (C++20 起)
template< class T >
constexpr T* to_address(T* p) noexcept;
(2) (C++20 起)

获得 p 所指向的地址,而不形成到被指向者的引用:

1) 缀饰指针重载:若表达式 std::pointer_traits<Ptr>::to_address(p) 为良式,则返回该表达式的结果。否则,返回 std::to_address(p.operator->())
2) 裸指针重载:若 T 为函数类型,则程序为病式,否则返回不修改的 p

参数

p - 缀饰或裸指针

返回值

表示与 p 所表示者相同地址的裸指针。

可能的实现

template<class T>
constexpr T* to_address(T* p) noexcept
{
    static_assert(!std::is_function_v<T>);
    return p;
}
 
template<class T>
auto to_address(const T& p) noexcept
{
    if constexpr (requires{ std::pointer_traits<T>::to_address(p); }) {
        return std::pointer_traits<T>::to_address(p);
    } else {
        return std::to_address(p.operator->());
    }
}

注意

即使在 p 引用的存储中无已构造的对象时,也能使用 std::to_address ,该情况下不能用 std::addressof(*p) ,因为无可绑定 std::addressof 参数的合法对象。

示例

#include <memory>
 
template<class A>
auto allocator_new(A& a)
{
    auto p = a.allocate(1);
    try {
        std::allocator_traits<A>::construct(a, std::to_address(p));
    } catch (...) {
        a.deallocate(p, 1);
        throw;
    }
    return p;
}
 
template<class A>
void allocator_delete(A& a, typename std::allocator_traits<A>::pointer p)
{
    std::allocator_traits<A>::destroy(a, std::to_address(p));
    a.deallocate(p, 1);
}
 
int main()
{
    std::allocator<int> a;
    auto p = allocator_new(a);
    allocator_delete(a, p);
}


参阅

提供关于指针式类型的信息
(类模板)
[静态] (C++20)
从缀饰指针获得裸指针( pointer_to 的反函数)
(std::pointer_traits<Ptr> 的公开静态成员函数)