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и результатаthis->size()до вызоваresize_and_overwrite. Пустьpобозначает указатель на первый символ в памяти.- Равенство определяется так, как будто с помощью проверки
this->compare(0, k, p, k) == 0. - Символы в
[p + k,p + count]могут иметь неопределённые значения.
- Равенство определяется так, как будто с помощью проверки
- Вычисляет
std::move(op)(p, count). Пустьr— значение, возвращаемоеstd::move(op)(p, count). - Заменяет содержимое
*thisна[p,p + r)(что устанавливает длину*thisвr). Делает недействительными все указатели и ссылки на диапазон[p,p + count].
Программа некорректна, если r не имеет тип целого числа. Поведение не определено, если std::move(op)(p, count) вызывает исключение или изменяет p или count, r не входит в диапазон [0, count], или любой символ в диапазоне [p, p + r) имеет неопределённое значение.
Реализации рекомендуются избегать ненужных копий и выделений памяти, например, делая p равным указателю на начало области памяти с символами, выделенными для *this после вызова, что может быть идентично существующему хранилищу *this если count меньше или равно this->capacity().
Параметры
| count | - | максимальный возможный новый размер строки |
| op | - | объект-функция, используемый для установки нового содержимого строки |
Возвращаемое значение
(нет)
Исключения
std::length_error если count > this->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 |
Пример
Ссылка для тестирования примера: компилятор-исследователь.
#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)
{
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)
{
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';
}Возможный вывод:
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"
См. также
| изменяет количество хранимых символов (публичный член-функция) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/string/basic_string/resize_and_overwrite