Skip to main content

std::destroy_n() algorithm

// (1)
template< class ForwardIt, class Size >
ForwardIt destroy_n( ForwardIt first, Size n );

// (2)
template< class ExecutionPolicy, class ForwardIt, class Size >
ForwardIt destroy_n( ExecutionPolicy&& policy, ForwardIt first, Size n );
  • (1) Destroys the n objects in the range starting at first, as if by:

    for (; n > 0; (void) ++first, --n)
    std::destroy_at(std::addressof(*first));
  • (2) Same as (1), but executed according to policy.

Overload Resolution

These overloads participate in overload resolution only if std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>  (until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>  (since C++20) is true.

Parameters

first

The beginning of the range of elements to destroy.

n

The number of elements to destroy.

policy

The execution policy to use. See execution policy for details.

Type requirements

ForwardItLegacyForwardIterator

No increment, assignment, comparison, or indirection through valid instances of NoThrowForwardIt may throw exceptions.

Return value

The end of the range of objects that has been destroyed (i.e., std::next(first, n)).

Complexity

Linear in n.

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For none other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

destroy_n(1)

template<class ForwardIt, class Size>
constexpr // since C++20
ForwardIt destroy_n(ForwardIt first, Size n)
{
for (; n > 0; (void) ++first, --n)
std::destroy_at(std::addressof(*first));
return first;
}

Examples

Main.cpp
#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));

std::destroy_n(ptr, 8);
}
Output
0 destructed
1 destructed
2 destructed
3 destructed
4 destructed
5 destructed
6 destructed
7 destructed
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::destroy_n() algorithm

// (1)
template< class ForwardIt, class Size >
ForwardIt destroy_n( ForwardIt first, Size n );

// (2)
template< class ExecutionPolicy, class ForwardIt, class Size >
ForwardIt destroy_n( ExecutionPolicy&& policy, ForwardIt first, Size n );
  • (1) Destroys the n objects in the range starting at first, as if by:

    for (; n > 0; (void) ++first, --n)
    std::destroy_at(std::addressof(*first));
  • (2) Same as (1), but executed according to policy.

Overload Resolution

These overloads participate in overload resolution only if std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>  (until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>  (since C++20) is true.

Parameters

first

The beginning of the range of elements to destroy.

n

The number of elements to destroy.

policy

The execution policy to use. See execution policy for details.

Type requirements

ForwardItLegacyForwardIterator

No increment, assignment, comparison, or indirection through valid instances of NoThrowForwardIt may throw exceptions.

Return value

The end of the range of objects that has been destroyed (i.e., std::next(first, n)).

Complexity

Linear in n.

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For none other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

destroy_n(1)

template<class ForwardIt, class Size>
constexpr // since C++20
ForwardIt destroy_n(ForwardIt first, Size n)
{
for (; n > 0; (void) ++first, --n)
std::destroy_at(std::addressof(*first));
return first;
}

Examples

Main.cpp
#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));

std::destroy_n(ptr, 8);
}
Output
0 destructed
1 destructed
2 destructed
3 destructed
4 destructed
5 destructed
6 destructed
7 destructed
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.