# std::ranges::destroy_at

< cpp‎ | memory

定义于头文件 `<memory>` |  |
调用签名 |  |
template< std::destructible T > constexpr void destroy_at( T* p ) noexcept; |  | (C++20 起)

若 `T` 不是数组类型，则在 `p` 所指向的对象上调用析构函数，如同通过 `p->~T()` 。否则，按顺序递归地销毁 *p 的元素，如同通过调用 std::destroy(std::begin(*p), std::end(*p)) 。

此页面上描述的仿函数实体是 niebloid ，即：

- 调用它们中的任何一者时不可指定显式模板实参。
- 它们无一对实参依赖查找可见。
- 在通常无限定查找寻找函数调用运算符左侧的名称找到它们之一时，它禁止实参依赖查找。

实际上，它们能以函数对象，或以某些特殊编译器扩展实现。

### 参数

p | - | 指向要被销毁的对象的指针

### 返回值

（无）

### 可能的实现

    struct destroy_at_fn {
      template<std::destructible T>
      constexpr void operator()(T *p) const noexcept
      {
        if constexpr (std::is_array_v<T>)
          for (auto &elem : *p)
            operator()(std::addressof(elem));
        else
          p->~T();
      }
    };

    inline constexpr destroy_at_fn destroy_at{};

### 注解

`destroy_at` 推导要被销毁的对象的类型，从而避免在析构函数调用中显式写出它。

在某常量表达式 e 的求值中调用 `destroy_at` 时，参数 `p` 必须指向生存期始于 e 的求值内的对象。

### 示例

下列示例演示如何用 `ranges::destroy_at` 销毁元素的相接序列。

    #include <memory>
    #include <new>
    #include <iostream>

    struct Tracer {
        int value;
        ~Tracer() { std::cout << value << " destructed\n"; }
    };

    int main()
    {
        alignas(Tracer) unsigned char buffer[sizeof(Tracer) * 8];

        for (int i = 0; i < 8; ++i)
            new(buffer + sizeof(Tracer) * i) Tracer{i}; // 手工构造对象

        auto ptr = std::launder(reinterpret_cast<Tracer*>(buffer));

        std::destroy_n(ptr, 8);
    }

输出：

    0 destructed
    1 destructed
    2 destructed
    3 destructed
    4 destructed
    5 destructed
    6 destructed
    7 destructed

### 参阅

ranges::destroy (C++20) | 销毁范围中的元素 (niebloid)
ranges::destroy_n (C++20) | 销毁范围中一定量的元素 (niebloid)
ranges::construct_at (C++20) | 在给定地址创建对象 (niebloid)
destroy_at (C++17) | 销毁在给定地址的对象 (函数模板)