std::basic_string<CharT,Traits,Allocator>::resize_and_overwrite
来自 cppreference.cn
< cpp | string | basic_string
template< class Operation > constexpr void resize_and_overwrite( size_type count, Operation op ); |
(C++23 起) | |
将字符串大小调整为最多包含 count 个字符,使用用户提供的操作 op 来修改可能不确定的内容并设置长度。这避免了在打算将适中大小的 std::string 用作字符数组(例如,由 C API 调用填充)时进行初始化所需的开销。
此函数执行以下步骤:
- 获取包含 count + 1 个字符的连续存储空间,并将其前 k 个字符等同于调用
resize_and_overwrite
之前 *this 的前 k 个字符,其中 k 是 count 和 size() 结果中较小的一个。令 p 指向存储空间中的第一个字符。- 相等性判断如同通过检查 this->compare(0, k, p, k) == 0。
- 位于
[
p + k,
p + count]
范围内的字符可能具有不确定的值。
- 评估 std::move(op)(p, count),令 r 为返回值。
- 用
[
p,
p + r)
替换 *this 的内容(这将 *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 分配的字符存储的起始指针,如果 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 成员函数) |