名稱空間
變體
操作

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

來自 cppreference.com
< cpp‎ | string‎ | basic_string
 
 
 
std::basic_string
 
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 個字元等同於呼叫 resize_and_overwrite 之前 *this 的前 k 個字元,其中 kcountsize() 結果中較小的一個。令 p 指向儲存空間中的第一個字元。
    • 相等性判斷如同透過檢查 this->compare(0, k, p, k) == 0
    • 位於 [p + kp + count] 範圍內的字元可能具有不確定的值。
  2. 評估 std::move(op)(p, count),令 r 為返回值。
  3. [pp + r) 替換 *this 的內容(這將 *this 的長度設定為 r)。使所有指向 [pp + count] 範圍的指標和引用失效。

如果 r 不是整數型別,則程式格式錯誤。

如果滿足以下任何條件,則行為是未定義的:

  • std::move(op)(p, count) 丟擲異常。
  • std::move(op)(p, count) 修改 pcount
  • r 不在 [0count] 範圍內。
  • 範圍 [pp + r) 中的任何字元都具有不確定的值。

建議實現透過以下方式避免不必要的複製和分配,例如,使 p 等於呼叫後為 *this 分配的字元儲存的起始指標,如果 count 小於或等於 capacity(),則此指標可能與 *this 的現有儲存相同。

目錄

[編輯] 引數

count - 字串可能的最大新大小
op - 用於設定字串新內容的函式物件

[編輯] 異常

如果 count > max_size(),則丟擲 std::length_error。由相應 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()
{
    // 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) 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';
 
    // The size shrinking case. Note, that the user's lambda is always invoked.
    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. 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"

[編輯] 另請參閱

更改儲存的字元數
(public 成員函式) [編輯]