std::to_address

< cpp‎ | memory
 
 
工具库
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)
swap 与类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

初等字符串转换
(C++17)
(C++17)
 
动态内存管理
智能指针
(C++11)
(C++11)
(C++11)
(C++17 前)
(C++11)
分配器
内存资源
未初始化存储
未初始化内存算法
有制约的未初始化内存算法
垃圾收集支持
杂项
to_address
(C++20)
(C++11)
(C++11)
C 库
低层内存管理
 
定义于头文件 <memory>
template< class Ptr >
constexpr 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>
constexpr 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 参数的合法对象。

to_address 的缀饰指针重载审查 std::pointer_traits<Ptr> 特化。若实例化该特化自身为谬构(往往是因为无法定义 element_type ),则导致立即语境外的硬错误并使得程序为谬构。

示例

#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> 的公开静态成员函数)