std::basic_string<CharT,Traits,Allocator>:: resize_and_overwrite
|
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:
-
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_overwriteist. 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.
- Wertet std :: move ( op ) ( p, count ) aus, sei r der Rückgabewert.
-
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) |