Espacios de nombres
Variantes

std::ranges::uninitialized_default_construct

De cppreference.com
 
 
Biblioteca de servicios
 
Gestión de memoria dinámica
Punteros inteligentes
(C++11)
(C++11)
(C++11)
(hasta C++17)
(C++11)
(C++23)
Asignadores de memoria
Recursos de memoria
Almacenamiento no inicializado
Algoritmos de memoria no inicializada
Algoritmos restringidos de memoria no inicializada
Apoyo para recolección de basura
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
Misceláneos
(C++20)
(C++11)
(C++11)
 
<tbody> </tbody>
Definido en el archivo de encabezado <memory>
Signatura de la llamada
template <no-throw-forward-iterator I, no-throw-sentinel-for<I> S> requires std::default_initializable<std::iter_value_t<I>> I uninitialized_default_construct( I first, S last );
(1) (desde C++20)
template <no-throw-forward-range R> requires std::default_initializable<ranges::range_value_t<R>> ranges::borrowed_iterator_t<R> uninitialized_default_construct( R&& r );
(2) (desde C++20)
1) Construye objetos de tipo std::iter_value_t<I> en el almacenamiento no inicializado designado por el rango [first, last) por la inicialización por defecto, como si fuera por
for (; first != last; ++first)
  ::new (const_cast<void*>(static_cast<const volatile void*>(std::addressof(*first))))
      std::remove_reference_t<std::iter_reference_t<I>>;
Si se lanza una excepción durante la inicialización, los objetos ya construidos se destruyen en un orden no especificado.
2) Igual que (1), pero usa r como rango, como si se usara ranges::begin(r) como first, y ranges::end(r) como last.

Las entidades similares a funciones descritas en esta página son niebloids, es decir:

En la práctica, pueden implementarse como objetos función o con extensiones de compilador especiales.

Parámetros

first, last - Par iterador-centinela que denota el rango de los elementos a inicializar.
r - El rango de elementos a inicializar.

Valor de retorno

Un iterador igual a last.

Complejidad

Lineal en la distancia entre first y last.

Excepciones

La excepción lanzada en la construcción de los elementos en el rango de destino, si existe.

Notas

Una implementación puede omitir la construcción de objetos (sin cambiar el efecto observable) si no se llama a un constructor por defecto no trivial mientras se inicializa por defecto un objeto std::iter_value_t<I>, que puede ser detectado por std::is_trivially_default_constructible_v.

Posible implementación

struct uninitialized_default_construct_fn {
    template <no-throw-forward-iterator I, no-throw-sentinel-for<I> S>
    requires std::default_initializable<std::iter_value_t<I>>
    I operator()( I first, S last ) const {
        using ValueType = std::remove_reference_t<std::iter_reference_t<I>>;
        if constexpr (std::is_trivially_default_constructible_v<ValueType>)
            return ranges::next(first, last); // skip initialization
        I rollback {first};
        try {
            for (; !(first == last); ++first)
                ::new (const_cast<void*>(static_cast<const volatile void*>
                        (std::addressof(*first)))) ValueType;
            return first;
        } catch (...) { // rollback: destruir los elementos construidos
            for (; rollback != first; ++rollback)
                ranges::destroy_at(std::addressof(*rollback));
            throw;
        }
    }

    template <no-throw-forward-range R>
    requires std::default_initializable<ranges::range_value_t<R>>
    ranges::borrowed_iterator_t<R>
    operator()( R&& r ) const {
        return (*this)(ranges::begin(r), ranges::end(r));
    }
};

inline constexpr uninitialized_default_construct_fn uninitialized_default_construct{};

Ejemplo

#include <cstring>
#include <iostream>
#include <memory>
#include <string>

int main()
{
    struct S { std::string m{ "▄▀▄▀▄▀▄▀" }; };

    constexpr int n {4};
    alignas(alignof(S)) char out[n * sizeof(S)];

    try
    {
        auto first {reinterpret_cast<S*>(out)};
        auto last {first + n};

        std::ranges::uninitialized_default_construct(first, last);

        auto count {1};
        for (auto it {first}; it != last; ++it) {
            std::cout << count++ << ' ' << it->m << '\n';
        }

        std::ranges::destroy(first, last);
    }
    catch(...) { std::cout << "¡Excepción!\n"; }

    // Observa que para "tipos triviales" uninitialized_default_construct
    // generalmente no llena con ceros el área de memoria no inicializada dada.
    constexpr char etalon[] { 'A', 'B', 'C', 'D', '\n' };
    char v[] { 'A', 'B', 'C', 'D', '\n' };
    std::ranges::uninitialized_default_construct(std::begin(v), std::end(v));
    if (std::memcmp(v, etalon, sizeof(v)) == 0) {
        std::cout << "  ";
        // Tal vez comportamiento no definido, pendiente CWG 1997:
        // for (const char c : v) { std::cout << c << ' '; }
        for (const char c : etalon) { std::cout << c << ' '; }
    } else {
        std::cout << "Unspecified\n";
    }
}

Posible salida:

1 ▄▀▄▀▄▀▄▀
2 ▄▀▄▀▄▀▄▀
3 ▄▀▄▀▄▀▄▀
4 ▄▀▄▀▄▀▄▀
  A B C D

Véase también


(niebloid) [editar]
Construye objetos mediante la inicialización de un valor en un área de memoria sin inicializar, definido por un rango.
(niebloid) [editar]
Construye objetos mediante la inicialización de un valor en un área de memoria sin inicializar, definido por un inicio y una cuenta.
(niebloid) [editar]
Construye objetos mediante la inicialización por defecto en un área de memoria sin inicializar, definido por un rango.
(plantilla de función) [editar]