Namensräume
Varianten
Aktionen

std::ranges::uninitialized_move_n, std::ranges::uninitialized_move_n_result

Von cppreference.com
< cpp‎ | memory
 
 
Speicherverwaltungsbibliothek
(nur Exposition*)
Algorithmen für uninitialisierten Speicher
(C++17)
(C++17)
(C++17)
Beschränkte uninitialisierte
Speicher-Algorithmen
ranges::uninitialized_move_n
(C++20)
C-Bibliothek

Allocatoren
Speicherressourcen
Unterstützung für Garbage Collection
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
Uninitialisierter Speicher
Explizites Lebenszeitmanagement
 
Definiert in Header <memory>
Aufruf-Signatur
template< std::input_iterator I,

          no-throw-forward-iterator O, no-throw-sentinel-for<O> S >
    requires std::constructible_from<std::iter_value_t<O>,
                                     std::iter_rvalue_reference_t<I>>
uninitialized_move_n_result<I, O>
    uninitialized_move_n( I ifirst, std::iter_difference_t<I> count,

                          O ofirst, S olast );
(1) (seit C++20)
(constexpr seit C++26)
Hilfstypen
template< class I, class O >
using uninitialized_move_n_result = ranges::in_out_result<I, O>;
(2) (seit C++20)

Sei N gleich ranges::min(count, ranges::distance(ofirst, olast)).

Kopiert N Elemente aus dem Bereich, der bei ifirst beginnt (mittels semantischem Verschieben, falls unterstützt) in einen uninitialisierten Speicherbereich [ofirstolast), als ob durch auto ret = ranges::uninitialized_move(std::counted_iterator(std::move(ifirst), count),
                                      std::default_sentinel, ofirst, olast);
return {std::move(ret.in).base(), ret.out};

Wenn während der Initialisierung eine Ausnahme ausgelöst wird, werden die bereits im Bereich [ofirstolast) konstruierten Objekte in einer nicht spezifizierten Reihenfolge zerstört. Außerdem werden die Objekte im Eingabebereich, der bei ifirst beginnt und bereits verschoben wurden, in einem gültigen, aber nicht spezifizierten Zustand hinterlassen.

Wenn [ofirstolast) mit ifirst + [0count) überlappt, ist das Verhalten undefiniert.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als niebloids bekannt), d.h.

Inhalt

[bearbeiten] Parameter

ifirst - der Anfang des Eingabebereichs von Elementen, die verschoben werden sollen
ofirst, olast - das Iterator-Sentinel-Paar, das den Ausgabebereich von zu initialisierenden Elementen definiert Bereich
n - die Anzahl der zu verschiebenden Elemente

[bearbeiten] Rückgabewert

Wie oben beschrieben.

[bearbeiten] Komplexität

𝓞(N).

[bearbeiten] Ausnahmen

Jegliche Ausnahme, die bei der Konstruktion der Elemente im Zielbereich ausgelöst wird.

[bearbeiten] Hinweise

Eine Implementierung kann die Effizienz von ranges::uninitialized_move_n verbessern, z. B. durch Verwendung von ranges::copy_n, wenn der Werttyp des Ausgabebereichs ein TrivialType ist.

Feature-Test-Makro Wert Std Feature
__cpp_lib_raw_memory_algorithms 202411L (C++26) constexpr für spezialisierte Speicher-Algorithmen, (1)

[bearbeiten] Mögliche Implementierung

struct uninitialized_move_n_fn
{
    template<std::input_iterator I,
             no-throw-forward-iterator O, no-throw-sentinel-for<O> S>
        requires std::constructible_from<std::iter_value_t<O>,
                                         std::iter_rvalue_reference_t<I>>
    constexpr ranges::uninitialized_move_n_result<I, O>
        operator()(I ifirst, std::iter_difference_t<I> count, O ofirst, S olast) const
    {
        auto iter = std::counted_iterator(std::move(ifirst), count);
        auto ret = ranges::uninitialized_move(iter, std::default_sentinel, ofirst, olast);
        return {std::move(ret.in).base(), ret.out};
    }
};
 
inline constexpr uninitialized_move_n_fn uninitialized_move_n{};

[bearbeiten] Beispiel

#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[]{ "No", "Diagnostic", "Required", };
    print("initially, in: ", 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::ranges::uninitialized_move_n(std::begin(in), sz, first, last);
 
            print("after move, in: ", std::begin(in), std::end(in));
            print("after move, out: ", first, last);
 
            std::ranges::destroy(first, last);
        }
        catch (...)
        {
            std::cout << "Exception!\n";
        }
        std::free(out);
    }
}

Mögliche Ausgabe

initially, in: "No" "Diagnostic" "Required"
after move, in: "" "" ""
after move, out: "No" "Diagnostic" "Required"

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 3870 C++20 dieser Algorithmus kann Objekte auf einem const Speicher erstellen nicht erlaubt

[bearbeiten] Siehe auch

verschiebt einen Bereich von Objekten in einen uninitialisierten Speicherbereich
(Algorithmus-Funktionsobjekt)[edit]
verschiebt eine Anzahl von Objekten in einen uninitialisierten Speicherbereich
(Funktions-Template) [edit]