std::basic_string<CharT,Traits,Allocator>:: resize_and_overwrite
|
template
<
class
Operation
>
constexpr void resize_and_overwrite ( size_type count, Operation op ) ; |
(начиная с C++23) | |
Изменяет размер строки, чтобы она содержала не более count символов, используя предоставленную пользователем операцию op для модификации возможно неопределенного содержимого и установки длины. Это позволяет избежать затрат на инициализацию строки std::string подходящего размера, когда она предназначена для использования в качестве массива символов, который будет заполняться, например, вызовом C API.
Эта функция выполняет следующие шаги:
-
Получает непрерывную область памяти, содержащую
count
+
1
символов, и делает её первые
k
символов равными первым
k
символам
*
this
, где
k
— меньшее из значений
count
и результата вызова
size
(
)
до вызова
resize_and_overwrite. Обозначим через p указатель на первый символ в этой области памяти.- Равенство определяется как если бы проверялось this - > compare ( 0 , k, p, k ) == 0 .
-
Символы в диапазоне
[p + k,p + count]могут иметь неопределённые значения.
- Выполняет std :: move ( op ) ( p, count ) , пусть r будет возвращаемым значением.
-
Заменяет содержимое
*
this
на
[p,p + r)(что устанавливает длину * this в r ). Инвалидирует все указатели и ссылки на диапазон[p,p + count].
Если r не является целочисленным типом , программа является некорректной.
Если выполняется любое из следующих условий, поведение не определено:
- std :: move ( op ) ( p, count ) выбрасывает исключение.
- std :: move ( op ) ( p, count ) изменяет p или count .
-
r
находится вне диапазона
[ 0 ,count]. -
Любой символ в диапазоне
[p,p + r)имеет неопределенное значение.
Рекомендуется, чтобы реализации избегали ненужных копирований и выделений памяти, например, устанавливая p равным указателю на начало хранилища символов, выделенного для * this после вызова, которое может совпадать с существующим хранилищем * this , если count меньше или равно capacity ( ) .
Содержание |
Параметры
| count | - | максимально возможный новый размер строки |
| op | - | функциональный объект, используемый для установки нового содержимого строки |
Исключения
std::length_error
если
count
>
max_size
(
)
.
Любые исключения, выброшенные соответствующим
Allocator
.
Если исключение выбрасывается из std :: move ( op ) ( p, count ) , поведение не определено. В противном случае, если исключение выбрасывается, эта функция не имеет эффекта.
Примечания
resize_and_overwrite
делает недействительными все итераторы, указатели и ссылки на
*
this
, независимо от того, происходит ли перераспределение памяти. Реализации могут предполагать, что содержимое строки не является алиасированным после вызова
resize_and_overwrite
.
| Макрос тестирования возможностей | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_lib_string_resize_and_overwrite
|
202110L
|
(C++23) |
std::basic_string::resize_and_overwrite
|
Пример
Ссылка для тестирования примера: 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[]{"яблоко", "банан", "кокос", "дата", "бузина"}; int main() { // Простой случай, добавление только fruits[0]. Размер строки будет увеличен. std::string s{"Еда: "}; 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 (Примечание: Согласно требованиям, HTML-теги и атрибуты не переведены, термин `std::quoted` как специфический для C++ оставлен без изменения)(s) << '\n'; // Случай уменьшения размера. Обратите внимание, что пользовательская лямбда всегда вызывается. 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. Копировать данные до заполнения буфера. Вывести данные и размеры.\n"; std::string food{"Еда:"}; const auto resize_to{27}; std::cout << "Изначально, 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] - это диапазон для присваивания // p[0]..p[min(n, food_size) - 1] - это диапазон для чтения // (содержимое изначально равно исходной строке) // Отладочный вывод: std::cout << "In Operation(); n: " << n << '\n'; // Копировать фрукты в буфер p, пока есть достаточно места. 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)}; // Отладочный вывод: std::cout << "In Operation(); final_size: " << final_size << '\n'; assert(final_size <= n); return final_size; // Возвращаемое значение - фактическая новая длина // строки, должно быть в диапазоне 0..n } ); std::cout << "Наконец, food.size: " << food.size() << ", food.capacity: " << food.capacity() << ", еда: " << std::quoted (Примечание: Согласно требованиям, HTML-теги и атрибуты не переведены, термин `std::quoted` как специфический для C++ оставлен без перевода)(food) << '\n'; }
Возможный вывод:
1. "Food: apple" 2. "Food" 3. Копировать данные до заполнения буфера. Вывести данные и размеры. Изначально, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:" В Operation(); n: 27 В Operation(); final_size: 26 В итоге, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"
Смотрите также
|
изменяет количество хранимых символов
(публичная функция-член) |