Namespaces
Variants

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

From cppreference.net
std::basic_string
template < class Operation >
constexpr void resize_and_overwrite ( size_type count, Operation op ) ;
(C++23부터)

문자열이 최대 count 개의 문자를 포함하도록 크기를 조정하며, 사용자가 제공한 연산 op 를 사용하여 불확정적인 내용을 수정하고 길이를 설정합니다. 이는 C API 호출 등으로 채워질 char 배열로 사용하려는 std::string 을 적절한 크기로 초기화하는 비용을 피할 수 있습니다.

이 함수는 다음 단계를 수행합니다:

  1. count + 1 개의 문자를 포함하는 연속 저장 공간을 획득하고, 그 중 첫 k 개 문자를 * this 의 첫 k 개 문자와 동일하게 설정합니다. 여기서 k count resize_and_overwrite 호출 전 size ( ) 결과 값 중 더 작은 값입니다. 저장 공간의 첫 번째 문자를 가리키는 포인터를 p 라고 합니다.
    • 동등성은 this - > compare ( 0 , k, p, k ) == 0 을 확인하는 것처럼 결정됩니다.
    • [ p + k , p + count ] 범위의 문자들은 불확정 값을 가질 수 있습니다.
  2. std :: move ( op ) ( p, count ) 를 평가하고, 반환 값을 r 이라고 합니다.
  3. * this 의 내용을 [ p , p + r ) 로 대체합니다 (이는 * this 의 길이를 r 으로 설정합니다). [ p , p + count ] 범위에 대한 모든 포인터와 참조를 무효화합니다.

만약 r integer-like type 이 아닌 경우, 프로그램의 형식이 잘못되었습니다.

다음 조건 중 하나라도 충족되면, 동작은 정의되지 않습니다:

  • std :: move ( op ) ( p, count ) 예외를 발생시킵니다.
  • std :: move ( op ) ( p, count ) p 또는 count 를 수정합니다.
  • r 이 범위 [ 0 , count ] 내에 있지 않습니다.
  • 범위 [ p , p + r ) 내의 모든 문자는 불확정된 값을 가집니다.

구현체는 불필요한 복사와 할당을 피하는 것이 권장되며, 예를 들어 p 를 호출 후 문자 저장을 위해 할당된 저장 공간의 시작 포인터로 설정하는 방식이 있습니다. 이는 * 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(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()
              << ", food: " << std::quoted(food) << '\n';
}

가능한 출력:

1. "Food: apple"
2. "Food"
3. 버퍼가 가득 찰 때까지 데이터를 복사합니다. 데이터와 크기를 출력합니다.
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"

참고 항목

저장된 문자 수를 변경합니다
(public member function)