Namespaces
Variants

std::basic_string<CharT,Traits,Allocator>:: resize_and_overwrite

From cppreference.net
std::basic_string
template < class Operation >
constexpr void resize_and_overwrite ( size_type count, Operation op ) ;
(seit C++23)

Ändert die Größe des Strings, um höchstens count Zeichen zu enthalten, wobei die benutzerdefinierte Operation op verwendet wird, um die möglicherweise unbestimmten Inhalte zu modifizieren und die Länge festzulegen. Dies vermeidet die Kosten der Initialisierung einer entsprechend dimensionierten std::string , wenn diese als Zeichenarray verwendet werden soll, das z.B. durch einen C-API-Aufruf gefüllt wird.

Diese Funktion führt die folgenden Schritte aus:

  1. Reserviert zusammenhängenden Speicher, der count + 1 Zeichen enthält, und setzt die ersten k Zeichen gleich den ersten k Zeichen von * this , wobei k der kleinere Wert von count und dem Ergebnis von size ( ) vor dem Aufruf von resize_and_overwrite ist. Sei p der Zeiger auf das erste Zeichen im Speicher.
    • Die Gleichheit wird bestimmt, als ob this - > compare ( 0 , k, p, k ) == 0 geprüft würde.
    • Die Zeichen in [ p + k , p + count ] können undefinierte Werte haben.
  2. Wertet std :: move ( op ) ( p, count ) aus, sei r der Rückgabewert.
  3. Ersetzt den Inhalt von * this durch [ p , p + r ) (was die Länge von * this auf r setzt). Macht alle Zeiger und Referenzen auf den Bereich [ p , p + count ] ungültig.

Wenn r kein integer-ähnlicher Typ ist, ist das Programm fehlerhaft.

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:

  • std :: move ( op ) ( p, count ) wirft eine Ausnahme.
  • std :: move ( op ) ( p, count ) modifiziert p oder count .
  • r liegt nicht im Bereich [ 0 , count ] .
  • Jedes Zeichen im Bereich [ p , p + r ) hat einen undefinierten Wert.

Implementierungen wird empfohlen, unnötige Kopien und Allokationen zu vermeiden, indem z.B. p gleich dem Zeiger auf den Anfang des Speicherbereichs für Zeichen gesetzt wird, der für * this nach dem Aufruf allokiert wurde, was identisch mit dem bestehenden Speicher von * this sein kann, falls count kleiner oder gleich capacity ( ) ist.

Inhaltsverzeichnis

Parameter

count - die maximal mögliche neue Größe der Zeichenkette
op - das Funktionsobjekt zum Festlegen der neuen Inhalte der Zeichenkette

Exceptions

std::length_error falls count > max_size ( ) . Alle Ausnahmen, die vom entsprechenden Allocator geworfen werden.

Wenn eine Ausnahme aus std :: move ( op ) ( p, count ) geworfen wird, ist das Verhalten undefiniert. Andernfalls, wenn eine Ausnahme geworfen wird, hat diese Funktion keine Wirkung.

Hinweise

resize_and_overwrite macht alle Iteratoren, Zeiger und Referenzen auf * this ungültig, unabhängig davon, ob eine Reallokation stattfindet. Implementierungen können davon ausgehen, dass der Inhalt der Zeichenkette nach dem Aufruf von resize_and_overwrite nicht gealiast wird.

Feature-Test Makro Wert Standard Funktion
__cpp_lib_string_resize_and_overwrite 202110L (C++23) std::basic_string::resize_and_overwrite

Beispiel

Link zum Testen des Beispiels: compiler explorer .

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
static_assert(__cpp_lib_string_resize_and_overwrite);
constexpr std::string_view fruits[]{"Apfel", "Banane", "Kokosnuss", "Datum", "Elderberry"};
int main()
{
    // Ein einfacher Fall, nur fruits[0] anhängen. Die String-Größe wird erhöht.
    std::string s{"Essen: "};
    s.resize_and_overwrite(16, [sz = s.size()](char* buf, std::size_t buf_size) noexcept
    {
        const auto to_copy = std::min(buf_size - sz, fruits[0].size());
        std::memcpy(buf + sz, fruits[0].data(), to_copy);
        return sz + to_copy;
    });
    std::cout << "1. " << std::quoted(s) << '\n';
    // Der Fall der Größenverringerung. Beachten Sie, dass die Lambda-Funktion des Benutzers immer aufgerufen wird.
    s.resize_and_overwrite(10, [](char* buf, int n) noexcept
    {
        return std::find(buf, buf + n, ':') - buf;
    });
    std::cout << "2. " << std::quoted(s) << '\n';
    std::cout << "3. Kopiere Daten, bis der Puffer voll ist. Drucke Daten und Größen.\n";
    std::string food{"Essen:"};
    const auto resize_to{27};
    std::cout << "Anfänglich, food.size: " << food.size()
              << ", food.capacity: " << food.capacity()
              << ", resize_to: " << resize_to
              << ", food: " << std::quoted(food) << '\n';
    food.resize_and_overwrite
    (
        resize_to,
        [food_size = food.size()](char* p, std::size_t n) noexcept -> std::size_t
        {
            // p[0]..p[n] ist der zuweisbare Bereich
            // p[0]..p[min(n, food_size) - 1] ist der lesbare Bereich
            // (Inhalt anfangs gleich dem ursprünglichen String)
            // Debug-Ausgabe:
            std::cout << "In Operation(); n: " << n << '\n';
            // Kopiere Früchte in den Puffer p, solange genügend Platz vorhanden ist.
            char* first = p + food_size;
            for (char* const end = p + n; const std::string_view fruit : fruits)
            {
                char* last = first + fruit.size() + 1;
                if (last > end)
                    break;
                *first++ = ' ';
                std::ranges::copy(fruit, first);
                first = last;
            }
            const auto final_size{static_cast<std::size_t>(first - p)};
            // Debug-Ausgabe:
            std::cout << "In Operation(); final_size: " << final_size << '\n';
            assert(final_size <= n);
            return final_size; // Rückgabewert ist die tatsächliche neue Länge
                               // des Strings, muss im Bereich 0..n liegen
        }
    );
    std::cout << "Finally, food.size: " << food.size()
              << ", food.capacity: " << food.capacity()
              << ", food: " << std::quoted(food) << '\n';
}

Mögliche Ausgabe:

1. "Food: apple"
2. "Food"
3. Kopiere Daten, bis der Puffer voll ist. Drucke Daten und Größen.
Anfangs, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:"
In Operation(); n: 27
In Operation(); final_size: 26
Schließlich, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"

Siehe auch

ändert die Anzahl der gespeicherten Zeichen
(öffentliche Elementfunktion)