std::uninitialized_move_n
De cppreference.com
<tbody>
</tbody>
| Definido en el archivo de encabezado <memory>
|
||
template< class InputIt, class Size, class NoThrowForwardIt > std::pair<InputIt, NoThrowForwardIt> uninitialized_move_n( InputIt first, Size count, NoThrowForwardIt d_first ); |
(1) | (desde C++17) |
template< class ExecutionPolicy, class ForwardIt, class Size, class NoThrowForwardIt > std::pair<ForwardIt, NoThrowForwardIt> uninitialized_move_n( ExecutionPolicy&& policy, ForwardIt first, Size count, NoThrowForwardIt d_first ); |
(2) | (desde C++17) |
1) Moves
count elements from a range beginning at first a un área de memoria no inicializada que comienza en d_first como si fuera por
for ( ; n > 0; ++d_first, (void) ++first, --n)
::new (/*VOIDIFICAR*/(*d_first))
typename std::iterator_traits<NoThrowForwardIt>::value_type(std::move(*first));
donde /*VOIDIFICAR*/(e) es:
|
(hasta C++20) |
|
(desde C++20) |
Si se lanza una excepción durante la inicialización, algunos objetos en el rango de origen se dejan en un estado válido pero no especificado, y los objetos ya construidos se destruyen en un orden no especificado.
2) Igual que (1), pero ejecutado de acuerdo con
policy. Esta sobrecarga no participa en la resolución de sobrecarga a menos que std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> (hasta C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> (desde C++20) sea verdadera.Parámetros
| first | - | El comienzo del rango de los elementos a mover. |
| d_first | - | El comienzo del rango de destino. |
| count | - | El número de elementos a mover. |
| policy | - | La política de ejecución a usar. Véase política de ejecución para más detalles. |
| Requisitos de tipo | ||
-InputIt debe satisfacer los requisitos de InputIterator.
| ||
-ForwardIt debe satisfacer los requisitos de ForwardIterator.
| ||
-NoThrowForwardIt debe satisfacer los requisitos de ForwardIterator.
| ||
-Ningún incremento, asignación, comparación o direccionamiento indirecto a través de instancias válidas de NoThrowForwardIt puede lanzar excepciones.
| ||
Valor de retorno
Un std::pair cuyo primer elemento es un iterador al elemento más allá del último elemento movido en el rango de origen y cuyo segundo elemento es un iterador al elemento más allá del último elemento movido en el rango de destino.
Complejidad
Lineal en count.
Excepciones
La sobrecarga con un parámetro de plantilla llamado ExecutionPolicy (política de ejecución) reporta errores tales que:
- Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y la política de ejecución es una de las tres políticas estándar, se llama a std::terminate. Para cualquier otra política de ejecución, el comportamiento está definido por la implementación.
- Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.
Posible implementación
template<class InputIt, class Size, class NoThrowForwardIt>
std::pair<InputIt, NoThrowForwardIt>
uninitialized_move_n(InputIt first, Size count, NoThrowForwardIt d_first)
{
using Value = typename std::iterator_traits<NoThrowForwardIt>::value_type;
NoThrowForwardIt current = d_first;
try {
for (; count > 0; ++first, (void) ++current, --count) {
::new (const_cast<void*>(static_cast<const volatile void*>(
std::addressof(*current)))) Value(std::move(*first));
}
} catch (...) {
std::destroy(d_first, current);
throw;
}
return {first, current};
}
|
Ejemplo
Ejecuta este código
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
void print(auto rem, auto first, auto last) {
for (std::cout << rem; first != last; ++first)
std::cout << std::quoted(*first) << ' ';
std::cout << '\n';
}
int main() {
std::string in[] { "One", "Definition", "Rule" };
print("Inicialmente, in es: ", std::begin(in), std::end(in));
if (
constexpr auto sz = std::size(in);
void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz)
) {
try {
auto first {static_cast<std::string*>(out)};
auto last {first + sz};
std::uninitialized_move_n(std::begin(in), sz, first);
print("Después del movimiento, in es: ", std::begin(in), std::end(in));
print("Después del movimiento, out es: ", first, last);
std::destroy(first, last);
}
catch (...) {
std::cout << "¡Excepción!\n";
}
std::free(out);
}
}
Posible salida:
Inicialmente, in es: "One" "Definition" "Rule"
Después del movimiento, in es: "" "" ""
Después del movimiento, out es: "One" "Definition" "Rule"
Véase también
(C++17) |
Mueve un rango de objetos a un área de memoria sin inicializar. (niebloid) |
(C++11) |
Copia un número de objetos a un área de memoria sin inicializar. (plantilla de función) |
(C++20) |
Mueve un número de objetos a un área de memoria sin inicializar. (niebloid) |