跳到主要内容

std::string resize_and_overwrite() 方法

// Non const version only
template< class Operation >
constexpr void resize_and_overwrite( size_type count, Operation op );

使用用户提供的操作 op 调整字符串大小以包含最多 count 个字符,并修改可能不确定的内容并设置长度。
这避免了在使用 C API 调用等方式填充字符串时,初始化大小合适的 std::string(作为字符数组使用)的开销。

此函数执行以下步骤:

  • (1) 获取包含 count + 1 个字符的连续存储空间,并使其前 k 个字符等于 *this 的前 k 个字符,其中 kcount 和在调用 resize_and_overwrite() 之前 this->size() 结果中的较小者。
    p 为存储空间中第一个字符的指针.

    • 等同性通过检查 this->compare(0, k, p, k) == 0 来确定。
    • [p + k, p + count ] 中的字符可能具有不确定的值。
  • (2) 评估 std::move(op)(p, count)
    rstd::move(op)(p, count) 的返回值。

  • (3)[ p, p + r ) 替换 *this 的内容(这将 *this 的长度设置为 r)。

失效

使范围 [ p, p + count ] 的所有指针和引用失效。

重要

如果 r 不具有整数类型,则程序格式错误

未定义行为

行为未定义

如果 std::move(op)(p, count) 抛出异常或修改 pcountr 不在范围 [ 0, count ] 内,或者范围 [ p, p + r ) 中的任何字符具有不确定的值。

参数

  • count - 字符串可能的最大新大小
  • op - 用于设置字符串新内容的函数对象

返回值

(无)

复杂度

重要

本节需要改进。您可以通过编辑此文档页面来帮助我们。

异常

如果 count > max_size(),则为 std::length_error。任何由相应 Allocator 抛出的异常。

未定义行为

如果 std::move(op)(p, count) 抛出异常,则行为未定义

。否则,如果抛出异常,此函数没有效果(强异常保证)。

备注

失效

resize_and_overwrite() 使 *this 中的所有迭代器指针引用失效,无论是否发生重新分配。

实现可以假定在调用 resize_and_overwrite() 后,字符串的内容没有别名。

建议实现通过以下方式避免不必要的复制和分配,例如,使 p 等于调用后分配给 *this 的字符存储的起始指针,如果 count 小于或等于 capacity(),则该指针可以与 *this 的现有存储相同。

功能测试宏:__cpp_lib_string_resize_and_overwrite

示例

Main.cpp
#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) {
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) {
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"
本文源自此 CppReference 页面。它可能为了改进或编辑偏好而被修改。单击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。

std::string resize_and_overwrite() 方法

// Non const version only
template< class Operation >
constexpr void resize_and_overwrite( size_type count, Operation op );

使用用户提供的操作 op 调整字符串大小以包含最多 count 个字符,并修改可能不确定的内容并设置长度。
这避免了在使用 C API 调用等方式填充字符串时,初始化大小合适的 std::string(作为字符数组使用)的开销。

此函数执行以下步骤:

  • (1) 获取包含 count + 1 个字符的连续存储空间,并使其前 k 个字符等于 *this 的前 k 个字符,其中 kcount 和在调用 resize_and_overwrite() 之前 this->size() 结果中的较小者。
    p 为存储空间中第一个字符的指针.

    • 等同性通过检查 this->compare(0, k, p, k) == 0 来确定。
    • [p + k, p + count ] 中的字符可能具有不确定的值。
  • (2) 评估 std::move(op)(p, count)
    rstd::move(op)(p, count) 的返回值。

  • (3)[ p, p + r ) 替换 *this 的内容(这将 *this 的长度设置为 r)。

失效

使范围 [ p, p + count ] 的所有指针和引用失效。

重要

如果 r 不具有整数类型,则程序格式错误

未定义行为

行为未定义

如果 std::move(op)(p, count) 抛出异常或修改 pcountr 不在范围 [ 0, count ] 内,或者范围 [ p, p + r ) 中的任何字符具有不确定的值。

参数

  • count - 字符串可能的最大新大小
  • op - 用于设置字符串新内容的函数对象

返回值

(无)

复杂度

重要

本节需要改进。您可以通过编辑此文档页面来帮助我们。

异常

如果 count > max_size(),则为 std::length_error。任何由相应 Allocator 抛出的异常。

未定义行为

如果 std::move(op)(p, count) 抛出异常,则行为未定义

。否则,如果抛出异常,此函数没有效果(强异常保证)。

备注

失效

resize_and_overwrite() 使 *this 中的所有迭代器指针引用失效,无论是否发生重新分配。

实现可以假定在调用 resize_and_overwrite() 后,字符串的内容没有别名。

建议实现通过以下方式避免不必要的复制和分配,例如,使 p 等于调用后分配给 *this 的字符存储的起始指针,如果 count 小于或等于 capacity(),则该指针可以与 *this 的现有存储相同。

功能测试宏:__cpp_lib_string_resize_and_overwrite

示例

Main.cpp
#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) {
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) {
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"
本文源自此 CppReference 页面。它可能为了改进或编辑偏好而被修改。单击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。