Namensräume
Varianten
Aktionen

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

Von cppreference.com
< cpp‎ | string‎ | basic string
 
 
 
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 auf maximal count Zeichen und verwendet die vom Benutzer bereitgestellte Operation op, um den möglicherweise unbestimmten Inhalt zu modifizieren und die Länge festzulegen. Dies vermeidet die Kosten für die Initialisierung eines ausreichend großen std::string, wenn dieser als Zeichenarray gedacht ist, das z. B. durch einen C-API-Aufruf gefüllt werden soll.

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 das 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 so bestimmt, als ob this->compare(0, k, p, k) == 0 geprüft würde.
    • Die Zeichen im Bereich [p + kp + 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 [pp + r) (was die Länge von *this auf r setzt). Macht alle Zeiger und Referenzen auf den Bereich [pp + count] ungültig.

Wenn r keinen integer-ähnlichen Typ hat, ist das Programm schlecht geformt.

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 [0count].
  • Jedes Zeichen im Bereich [pp + r) hat einen unbestimmten Wert.

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

Inhalt

[edit] Parameter

zählt - die maximal mögliche neue Größe des Strings
op - das Funktionsobjekt, das zum Setzen des neuen Inhalts des Strings verwendet wird

[edit] Ausnahmen

std::length_error, wenn count > max_size(). Alle Ausnahmen, die von der entsprechenden Allocator geworfen werden.

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

[edit] Hinweise

resize_and_overwrite macht alle Iteratoren, Zeiger und Referenzen auf *this ungültig, unabhängig davon, ob eine Neuzuweisung stattfindet. Implementierungen dürfen annehmen, dass der Inhalt des Strings nach dem Aufruf von resize_and_overwrite nicht aliased ist.

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

[edit] 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[]{"apple", "banana", "coconut", "date", "elderberry"};
 
int main()
{
    // A simple case, append only fruits[0]. The string size will be increased.
    std::string s{"Food: "};
    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';
 
    // The size shrinking case. Note, that the user's lambda is always invoked.
    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. Copy data until the buffer is full. Print data and sizes.\n";
    std::string food{"Food:"};
    const auto resize_to{27};
    std::cout << "Initially, 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] is the assignable range
            // p[0]..p[min(n, food_size) - 1] is the readable range
            // (contents initially equal to the original string)
 
            // Debug print:
            std::cout << "In Operation(); n: " << n << '\n';
 
            // Copy fruits to the buffer p while there is enough space.
            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 print:
            std::cout << "In Operation(); final_size: " << final_size << '\n';
 
            assert(final_size <= n);
            return final_size; // Return value is the actual new length
                               // of the string, must be in range 0..n
        }
    );
 
    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. Copy data until the buffer is full. Print data and sizes.
Initially, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:"
In Operation(); n: 27
In Operation(); final_size: 26
Finally, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"

[edit] Siehe auch

ändert die Anzahl der gespeicherten Zeichen
(public member function) [edit]