std::ranges::uninitialized_default_construct_n
Definido en el archivo de encabezado <memory>
|
||
Signatura de la llamada |
||
template <no-throw-forward-iterator I> requires std::default_initializable<std::iter_value_t<I>> |
(desde C++20) | |
Construye n
objetos de tipo std::iter_value_t<I> en el área de memoria no inicializada que comienza en first
por la inicialización por defecto, como si fuera por
for (; n-- > 0; ++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.
Las entidades similares a funciones descritas en esta página son niebloids, es decir:
- Las listas de argumentos de plantilla explícitas no se pueden especificar al llamar a cualquiera de ellas.
- Ninguna de ellas es visible para la búsqueda dependiente de argumentos.
- Cuando alguna de ellas se encuentra mediante la búsqueda normal no calificada como el nombre a la izquierda del operador de llamada a función, se inhibe la búsqueda dependiente de argumentos.
En la práctica, pueden implementarse como objetos función o con extensiones de compilador especiales.
Contenido |
Parámetros
first | - | El comienzo del rango de elementos a inicializar. |
n | - | El número de elementos a construir. |
Valor de retorno
El fin del rango de objetos (es decir, ranges::next(first, n)).
Complejidad
Lineal en n.
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_n_fn { template <no-throw-forward-iterator I> requires std::default_initializable<std::iter_value_t<I>> I operator()( I first, std::iter_difference_t<I> n ) 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, n); // omitir la inicialización I rollback {first}; try { for (; n-- > 0; ++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; } } }; inline constexpr uninitialized_default_construct_n_fn uninitialized_default_construct_n{}; |
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 = std::ranges::uninitialized_default_construct_n(first, n); 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_n // generalmente no llena con ceros el área de memoria no inicializada dada. constexpr int etalon[] { 1, 2, 3, 4, 5, 6 }; int v[] { 1, 2, 3, 4, 5, 6 }; std::ranges::uninitialized_default_construct_n(std::begin(v), std::size(v)); if (std::memcmp(v, etalon, sizeof(v)) == 0) { // Tal vez comportamiento no definido, pendiente CWG 1997: // for (const int i : v) { std::cout << i << ' '; } for (const int i : etalon) { std::cout << i << ' '; } } else { std::cout << "Unspecified!"; } std::cout << '\n'; }
Posible salida:
1 █▓▒░ █▓▒░ 2 █▓▒░ █▓▒░ 3 █▓▒░ █▓▒░ 4 █▓▒░ █▓▒░ 1 2 3 4 5 6
Véase también
Construye objetos mediante la
inicialización por defecto en un área de memoria sin inicializar, definido por un rango. | |
Construye objetos mediante la inicialización de un valor en un área de memoria sin inicializar, definido por un rango. (niebloid) | |
Construye objetos mediante la inicialización de un valor en un área de memoria sin inicializar, definido por un inicio y una cuenta. (niebloid) | |
Construye objetos mediante la inicialización por defecto en un área de memoria sin inicializar, definido por un inicio y una cuenta. (plantilla de función) |