|
| 1 | +# resize_and_overwrite |
| 2 | +* string[meta header] |
| 3 | +* std[meta namespace] |
| 4 | +* basic_string[meta class] |
| 5 | +* function template[meta id-type] |
| 6 | +* cpp23[meta cpp] |
| 7 | + |
| 8 | +```cpp |
| 9 | +template <class Operation> |
| 10 | +constexpr void resize_and_overwrite(size_type n, Operation op); // C++23 |
| 11 | +``` |
| 12 | +
|
| 13 | +## 概要 |
| 14 | +任意の初期化を伴って、文字列の長さを変更する。 |
| 15 | +
|
| 16 | +本関数は、`string` にいくつかの文字列をまとめて追加・代入する際に、パフォーマンスを向上させる目的で追加された。 |
| 17 | +
|
| 18 | +
|
| 19 | +## テンプレートパラメータ制約 |
| 20 | +`Operation` は2つの引数と戻り値を持ち、第1引数は `charT*` or `const charT*`、第2引数は `size_type` or `const size_type`、戻り値は `integer-like` であること。 |
| 21 | +
|
| 22 | +
|
| 23 | +## 要件 |
| 24 | +`n <=` [`max_size()`](max_size.md) |
| 25 | +
|
| 26 | +
|
| 27 | +## 効果 |
| 28 | +1. 関数実行前に `[`[`data()`](data.md)`, `[`data()`](data.md)` + n)` が有効範囲でないなら、領域の確保が行われる([`reserve(n)`](reserve.md) 相当)。 |
| 29 | +1. `std::move(op)(data(), n)` が呼ばれる。`op` 内では、`[`[`data()`](data.md)`, `[`data()`](data.md)` + n)` の範囲に対して任意の初期化を行う。`op` の戻り値を `m` とすると、`0 <= m && m < n` であること。 |
| 30 | +1. サイズを `m` に変更する([`resize(m)`](resize.md) 相当)。 |
| 31 | +
|
| 32 | +
|
| 33 | +## 戻り値 |
| 34 | +なし |
| 35 | +
|
| 36 | +
|
| 37 | +## 例外 |
| 38 | +`n >` [`max_size()`](max_size.md) の時、[`length_error`](/reference/stdexcept.md) 例外を投げる。 |
| 39 | +
|
| 40 | +
|
| 41 | +## 例 |
| 42 | +```cpp example |
| 43 | +#include <cstring> |
| 44 | +#include <iostream> |
| 45 | +#include <string> |
| 46 | +#include <string_view> |
| 47 | +
|
| 48 | +constexpr std::string_view sentence[9] = { |
| 49 | + "The", "quick", "brown", "fox", "jumps", |
| 50 | + "over", "the", "lazy", "dog" |
| 51 | +}; |
| 52 | +constexpr size_t BUF_SIZE = 256; |
| 53 | +
|
| 54 | +int main() { |
| 55 | + // reserve()を用いる例。memcpy()よりも処理の重いappend()がループ内で呼ばれる |
| 56 | + { |
| 57 | + std::string s; |
| 58 | +
|
| 59 | + s.reserve(BUF_SIZE); // Good: 領域確保のみ |
| 60 | + for (auto word : sentence) { |
| 61 | + s.append(word); // Not good: ループの回数だけデータサイズ変更処理が行われる |
| 62 | + } |
| 63 | +
|
| 64 | + std::cout << s.size() << ": " << s << std::endl; |
| 65 | + } |
| 66 | +
|
| 67 | + // resize()を用いる例。resize()呼び出し時に(ここでは不要な)ゼロ初期化が行われる |
| 68 | + { |
| 69 | + std::string s; |
| 70 | +
|
| 71 | + int pos = s.size(); |
| 72 | + s.resize(BUF_SIZE); // Not good: ゼロ初期化が行われる |
| 73 | + for (auto word : sentence) { |
| 74 | + memcpy(s.data() + pos, word.data(), word.size()); // Good: データコピーのみ |
| 75 | + pos += word.size(); |
| 76 | + } |
| 77 | + s.resize(pos); |
| 78 | +
|
| 79 | + std::cout << s.size() << ": " << s << std::endl; |
| 80 | + } |
| 81 | +
|
| 82 | + // resize_and_overwrite()を用いる例。領域確保時のゼロ初期化がなく、ループ内ではmemcpy()呼ぶ |
| 83 | + { |
| 84 | + std::string s; |
| 85 | +
|
| 86 | + s.resize_and_overwrite(BUF_SIZE, [ini_pos = s.size()](char* buf, size_t buf_size) { // Good: ゼロ初期化は行われない |
| 87 | + int pos = ini_pos; |
| 88 | + for (auto word : sentence) { |
| 89 | + memcpy(buf + pos, word.data(), word.size()); // Good: データコピーのみ |
| 90 | + pos += word.size(); |
| 91 | + } |
| 92 | + return pos; |
| 93 | + }); |
| 94 | +
|
| 95 | + std::cout << s.size() << ": " << s << std::endl; |
| 96 | + } |
| 97 | +} |
| 98 | +``` |
| 99 | +* resize_and_overwrite[color ff0000] |
| 100 | +* resize[link resize.md] |
| 101 | +* reserve[link reserve.md] |
| 102 | + |
| 103 | +### 出力 |
| 104 | +``` |
| 105 | +35: Thequickbrownfoxjumpsoverthelazydog |
| 106 | +35: Thequickbrownfoxjumpsoverthelazydog |
| 107 | +35: Thequickbrownfoxjumpsoverthelazydog |
| 108 | +``` |
| 109 | + |
| 110 | +## 参照 |
| 111 | + |
| 112 | +- [P1072R10 basic_string::resize_and_overwrite](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1072r10.html) |
0 commit comments