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与调用size()之前结果两者中的较小值。令resize_and_overwrite表示指向存储中第一个字符的指针。p该等式的判定方式如同检查- 。
this->compare(0, k, p, k) == 0范围 - 内的字符可能具有不确定的值。
[p + k,p + count]计算
- 。
- ,令
std::move(op)(p, count)为返回值。r用 - 替换
*this的内容(这会将[p,p + r)的长度设置为*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 小于或等于 *this,则该指针可与 count 的现有存储相同。
capacity()
参数
| 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() { // 简单情况:仅追加 fruits[0]。字符串大小将增加。 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'; // 大小缩减的情况。注意:用户的 lambda 始终会被调用。 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{"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: " <<</
参见
|
更改存储的字符数量
(公开成员函数) |