Namespaces
Variants

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

Aus de.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 der Zeichenkette so, dass sie höchstens count Zeichen enthält, wobei die vom Benutzer bereitgestellte Operation op verwendet wird, um den möglicherweise unbestimmten Inhalt zu verändern und die Länge festzulegen. Dies vermeidet die Kosten für die Initialisierung einer passend großen std::string, wenn diese als Zeichen-Array verwendet werden soll, das z. B. durch einen C-API-Aufruf befüllt wird.

Diese Funktion führt die folgenden Schritte aus:

  1. Beschafft zusammenhängenden Speicher, der count + 1 Zeichen enthält, und macht seine ersten k Zeichen gleich den ersten k Zeichen von *this, wobei k die kleinere 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 überprüft würde.
    • Die Zeichen in [p + k, p + count] können unbestimmte 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) (wodurch die Länge von *this auf r gesetzt wird). Macht alle Zeiger und Referenzen auf den Bereich [p, p + count] ungültig.

Wenn r nicht von einem ganzzahlartigen Typ ist, ist das Programm fehlerhaft (ill-formed).

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

  • std::move(op)(p, count) eine Ausnahme wirft.
  • std::move(op)(p, count) p oder count verändert.
  • r nicht im Bereich [0, count] liegt.
  • Ein Zeichen im Bereich [p, p + r) einen unbestimmten Wert hat.

Implementierungen wird empfohlen, unnötige Kopien und Allokationen zu vermeiden, z. B. indem p gleich dem Zeiger auf den Beginn des Speichers von Zeichen gemacht wird, die für *this nach dem Aufruf allokiert wurden, was identisch mit dem vorhandenen Speicher von *this sein kann, falls count kleiner oder gleich capacity() ist.

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)