std::destroy_at(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸŽ€ std::destroy_at πŸŽ€

okay bestie, this is the std::destroy_at(3) page from the C++ Standard Libary manual, and it's giving tiny cleanup goblin energy in the best way πŸ’–. no cap.

✨ NAME ✨

std::destroy_at β€” yeah, that's literally the name, and it's the function that destroys an object for you 🫢.

🌸 Synopsis 🌸

Defined in header <memory>
template< class T >                 (since C++17)
void destroy_at( T* p );            (until C++20)
template< class T >                 (since C++20)
constexpr void destroy_at( T* p );

If T is not an array type, it calls the destructor of the object pointed to by p, as if by p->~T() ✨.

If T is an array type: 🚨 the program is ill-formed until C++20. Since C++20, it recursively destroys elements of *p in order, as if by calling std::destroy(std::begin(*p), std::end(*p)) πŸ’….

πŸ¦‹ Parameters πŸ¦‹

  • p β€” a pointer to the object to be destroyed πŸ’–.

πŸŽ€ Return value πŸŽ€

(none) β€” literally nothing comes back, bestie 🌸.

πŸ‘‘ Possible implementation πŸ‘‘

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 version:
// template<class T> void destroy_at(T* p) { p->~T(); }

πŸ’œ Notes πŸ’œ

destroy_at deduces the type of object to be destroyed and hence avoids writing it explicitly in the destructor call β€” the way that it just knows is lowkey iconic ✨.

When destroy_at is called in the evaluation of some constant expression e, the argument p must point to an object whose lifetime (since C++20) began within the evaluation of e 🫢.

🌈 Example 🌈

The following example demonstrates how to use destroy_at to destroy a contiguous sequence of elements πŸŽ€.

// Run this code

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

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}; //manually construct objects

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

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

⭐ Output ⭐

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

🧚 See also 🧚

  • destroy β€” destroys a range of objects (C++17, function template) πŸ¦‹
  • destroy_n β€” destroys a number of objects in a range (C++17, function template) πŸ’«
  • construct_at β€” creates an object at a given address (C++20, function template) 🌸
  • ranges::destroy_at β€” destroys an object at a given address (C++20, niebloid) πŸ‘‘

πŸ’– source/version: cppreference.com β€” date: 2024.06.10 πŸ’–

πŸ“¦ where this page comes from