# std::destroy_at

< cpp‎ | memory

定义于头文件 `<memory>` |  |
template< class T > void destroy_at( T* p ); |  | (C++17 起) (C++20 前)
template< class T > constexpr void destroy_at( T* p ); |  | (C++20 起)

若 `T` 不是数组类型，则调用 `p` 所指向对象的析构函数，如同用 `p->~T()` 。

若 `T` 是数组类型，则程序非良构 (C++20 前)按顺序递归地销毁 *p 的元素，如同通过调用 std::destroy(std::begin(*p), std::end(*p)) (C++20 起)。

### 参数

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

### 返回值

（无）

### 可能的实现

    template<class T>
    constexpr void destroy_at(T* p)
    {
        if constexpr (std::is_array_v<T>)
            for (auto &elem : *p)
                (destroy_at)(std::addressof(elem));
        else
            p->~T();
    }
    // C++17 版本：
    // template<class T> void destroy_at(T* p) { p->~T(); }

### 注解

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

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

### 示例

下列示例演示如何用 `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));

        for (int i = 0; i < 8; ++i)
            std::destroy_at(ptr + i);
    }

输出：

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

### 参阅

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