std::basic_string<CharT,Traits,Allocator>::resize_and_overwrite
来自cppreference.com
< cpp | string | basic string
template<class Operation > constexprvoid resize_and_overwrite( size_type count, Operation op ); | (C++23 起) | |
重设字符串大小以含有至多 count 个字符,用用户提供的操作 op 修改可能不确定的内容并设置长度。这样就避免了初始化大小合适的 std::string 时所产生的成本,当它打算作为要被填充的字符数组时,例如,C API 调用。
此函数执行下列步骤:
- 获得至少含有 count +1 个字符的存储,并使它的前 k 个字符等于 *this 的前 k 个字符,其中 k 是 count 与调用
resize_and_overwrite
前 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); constexprstd::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{constauto 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{returnstd::find(buf, buf + n, ':')- buf;});std::cout<<"2. "<<std::quoted(s)<<'\n'; std::cout<<"3. 复制数据直至缓冲区满。打印数据和大小。\n";std::string food{"Food:"};constauto 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'; // 在空间足够时,把水果复制到缓冲区 p 中。char* first = p + food_size; for(char*const end = p + n;conststd::string_view fruit : fruits){char* last = first + fruit.size()+1;if(last > end)break;*first++=' '; std::ranges::copy(fruit, first); first = last;} constauto 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"
[编辑]参阅
更改存储的字符数 (公开成员函数) |