最終更新日時(UTC):
が更新

履歴 編集

function template
<string>

std::basic_string::resize_and_overwrite(C++23)

template <class Operation>
constexpr void resize_and_overwrite(size_type n, Operation op); // C++23

概要

任意の初期化を伴って、文字列の長さを変更する。

本関数は、string にいくつかの文字列をまとめて追加・代入する際に、パフォーマンスを向上させる目的で追加された。

適格要件

Operation型の値 op は、下記を満たす呼び出し可能な型であること。

  • std::move(op)(data(), n) が有効(第1引数 data()charT*型、第2引数 nsize_type型)。
  • 戻り値型は integer-like を満たす。

事前条件

  • 呼び出された op が例外を投げないこと。
  • op の呼び出しで、第1引数・第2引数ともに変更されないこと。
  • r = std::move(op)(data(), n) とすると、0 <= r && r <= n であること。
  • [data(), data() + r) の範囲に未初期化の要素がないこと。

効果

  1. 関数実行前に [data(),data()+ n) が有効範囲でないなら、領域の確保が行われる(reserve(n) 相当)。新たな領域は初期化されないことに注意。
  2. std::move(op)(data(), n) が呼ばれる。op 内では、[data(),data()+ n) の範囲に対して任意の初期化を行う。
  3. op の戻り値を r とすると、サイズを r に変更する。

戻り値

なし

#include <cstring>
#include <iostream>
#include <string>
#include <string_view>

constexpr std::string_view sentence[9] = {
    "The", "quick", "brown", "fox", "jumps",
    "over", "the", "lazy", "dog"
};
constexpr size_t BUF_SIZE = 256;

int main() {
    // reserve()を用いる例。memcpy()よりも処理の重いappend()がループ内で呼ばれる
    {
        std::string s;

        s.reserve(BUF_SIZE); // Good: 領域確保のみ
        for (auto word : sentence) {
            s.append(word); // Not good: ループの回数だけデータサイズ変更処理が行われる
        }

        std::cout << s.size() << ": " << s << std::endl;
    }

    // resize()を用いる例。resize()呼び出し時に(ここでは不要な)ゼロ初期化が行われる
    {
        std::string s;

        int pos = s.size();
        s.resize(BUF_SIZE); // Not good: ゼロ初期化が行われる
        for (auto word : sentence) {
            memcpy(s.data() + pos, word.data(), word.size()); // Good: データコピーのみ
            pos += word.size();
        }
        s.resize(pos);

        std::cout << s.size() << ": " << s << std::endl;
    }

    // resize_and_overwrite()を用いる例。領域確保時のゼロ初期化がなく、ループ内ではmemcpy()呼ぶ
    {
        std::string s;

        s.resize_and_overwrite(BUF_SIZE, [ini_pos = s.size()](char* buf, size_t buf_size) { // Good: ゼロ初期化は行われない
            int pos = ini_pos;
            for (auto word : sentence) {
                memcpy(buf + pos, word.data(), word.size()); // Good: データコピーのみ
                pos += word.size();
            }
            return pos; // サイズを返す
        });

        std::cout << s.size() << ": " << s << std::endl;
    }
}

出力

35: Thequickbrownfoxjumpsoverthelazydog
35: Thequickbrownfoxjumpsoverthelazydog
35: Thequickbrownfoxjumpsoverthelazydog

参照