Пространства имён
Варианты
Действия

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

Материал из cppreference.com
< cpp‎ | string‎ | basic string
 
 
 
std::basic_string
Функции-элементы
Доступ к элементам
Итераторы
Ёмкость
Операции
basic_string::resize_and_overwrite
(C++23)  
Поиск
Константы
Правила вывода (C++17)
Функции, не являющиеся элементами
Ввод/Вывод
Сравнение
(до C++20)(до C++20)(до C++20)(до C++20)(до C++20)(C++20)
Числовые преобразования
(C++11)(C++11)(C++11)
(C++11)(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
Вспомогательные классы
 
template< class Operation >
constexpr void resize_and_overwrite( size_type count, Operation op );
(начиная с C++23)

Изменяет размер строки так, чтобы она содержала не более count символов, используя предоставленную пользователем операцию op для изменения возможно неопределённого содержимого и установки длины. Это позволяет избежать затрат на инициализацию std::string подходящего размера, когда она предназначена для использования в качестве массива символов для заполнения, например, вызовом C API.

Эта функция выполняет следующие шаги:

  1. Получает непрерывное хранилище, содержащее count + 1 символов, и делает его первые k символы равными первым k символам *this, где k меньшее из count и результат this->size() перед вызовом resize_and_overwrite. Пусть p обозначает указатель на первый символ в хранилище.
    • Равенство определяется как будто проверкой this->compare(0, k, p, k) == 0.
    • Символы в [p + kp + count] могут иметь неопределённые значения.
  2. Вычисляет std::move(op)(p, count). Пусть r будет возвращаемым значением std::move(op)(p, count).
  3. Заменяет содержимое *this на [pp + r) (что устанавливает длину *this в r). Делает недействительными все указатели и ссылки на диапазон [pp + count].

Программа будет неправильной, если r не имеет целочисленного типа. Поведение не определено, если std::move(op)(p, count) генерирует исключение или изменяет p или count, r не находится в диапазоне [0count], или любой символ в диапазоне [pp + 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

[править] Пример

Ссылка для проверки примера: 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()
{
    // Простой случай: добавляем только fruits[0]. Размер строки будет увеличен.
    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';
 
    // Случай для уменьшения размера. Обратите внимание, что лямбда-выражение
    // пользователя вызывается всегда.
 
    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. Копирует данные до тех пор, пока буфер не заполнится. "
                 "Распечатывает данные и размеры.\n";
    std::string food{"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 << "В Operation(); n: " << n << '\n';
 
            // Копирует fruits в буфер 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 << "В 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()
              << ", food: " << std::quoted(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"

[править] Смотрите также

изменяет количество сохранённых символов
(public функция-элемент) [править]