Geekになりたいママエンジニアのブログ

子育てを楽しみつつ空き時間に自己啓発をしているログです。投稿する内容はすべて個人の意見であり、所属する組織とは関係がありません。

std::string_view

c++17にて追加されたstd::string_viewについてのメモです。

std::string_viewとは

std::string_viewとは、所有権を持たない文字列のクラスです。"view"という名前が示すように既に存在している文字列を参照しているだけのオブジェクトです。参照元の文字列は変更できません。文字列の先頭へのポインタと文字列長を保持しています。

const char* chars { "test" };
std::string s = chars;
std::string_view sv = chars;

for (auto it = s.begin(); it < s.end(); ++it)
{
    printf("%c", *it);
}
printf("\n");

// 読み取り処理はstringとほぼ同様に行える
for (auto it = sv.begin(); it < sv.end(); ++it)
{
    printf("%c", *it);
}
printf("\n");

s[0] = 'a';
sv[0] = 'a'; // Error! 値を変えることはできない

s.append("1");
sv.append("2"); // Error! append関数はない

s.c_str();
sv.c_str(); // Error! c_str関数はない

デバッガを確認すると、string_viewは元々のconst char*配列のアドレスをそのまま保持していることがわかります。

f:id:wfalps:20190420062109p:plain
debuggerでの表示

string_viewが有効な場面

std::string_viewは、std::stringのconstメンバー関数をほぼ全て持っています。そのため、文字列に変更を加えないのであれば、std::stringとほぼ変わりなく使用することができます。std::string_viewを使うと文字列を実際に保持しないため、メモリ使用量を抑えられます。また、文字列のコピーも防ぐことができます。

string_viewの制限

  • string_viewは、誰かが保持するchar配列を参照しているだけなので、参照元の文字列が途中でなくなってしまうこともありえます。また、文字列の変更をすることもできません。
  • std::stringはnull文字'\0'で終わることが保証されていますが、std::string_viewは、null文字'\0'で終わることが保証されません。そのため、c_str()で中身を取り出すこともできません。

std::stringにはなくstd::string_viewにのみある関数

  • remove_prefix(n): 文字列の先頭アドレスを後ろにn文字ずらす
  • remove_suffix(n): 文字列の長さをn文字短くする

終端null文字のことを考えなくていいので、自由に参照範囲を決められるstring_viewならではの関数です。

まとめ

一時的な文字列を処理する際にはとても便利なクラスです。とはいえ、引数としてstring_viewを受け取る関数を定義するなどのケースではメモリの管理が複雑になりそうなので、気を付けた方がよさそうです。

std::stringとstd::string_viewの違いイメージ
std::stringとstd::string_viewの違いイメージ