yohhoyの日記

技術的メモをしていきたい日記

文字列ビューstd::string_view 利用ガイド

C++17標準ライブラリ文字列ビューstd::string_viewクラス*1利用上の注意点についてメモ。

まとめ:

  • string_viewクラス=文字列に対する読取専用のビュー
    • std::stringと同じくヌル終端文字列以外も正しく取り扱える。ヌル文字を途中に含むことができる。
  • string_viewクラスは参照先文字列の所有権を管理しない
    • 古き良き “生ポインタ(raw pointer)” 相当ととらえ、ダングリング(dangling)・ビュー*2には十分注意する。
  • 関数パラメータ型におけるstring_view利用は安全。(→id:yohhoy:20171113
    • ヌル終端文字列(const char*)もしくは文字列(const std::string&)へのビューを統一的・効率的に扱える。
    • 関数実装で所有権が必要になったらstd::stringへ格納(=文字列実体をコピー)する。
    • std::stringと異なり、string_view::dataメンバ関数はヌル終端文字列を保証しないため(→id:yohhoy:20120601)、ヌル終端文字列を要求するレガシーAPI呼び出し用途には適さない。
  • 関数戻り値型やクラスデータメンバとしてのstring_view利用には十分留意する。ダングリング・ビューのリスク有り。
    • 参照先オブジェクトの生存期間(lifetime)をドキュメント化すること。
  • 一時文字列オブジェクトを指すstring_view変数を明示的に作らないこと。
    • ローカル変数にはstring_view型ではなくauto&&利用を検討すべき。
// 文字列型stringを返す関数
std::string f();

std::string_view s1 = f();
// NG: 関数戻り値(一時文字列オブジェクト)は破棄済みのため
//     この時点でs1はダングリングビューとなっている。

auto&& s2 = f();
// OK: 関数戻り値(一時文字列オブジェクト)を右辺値参照型で受けると
//     その生存期間は変数s2のスコープが切れるまで延長される。

関連URL

*1:厳密には std::basic_string_view<charT, traits> クラステンプレート。簡単のため本文中ではクラスとして説明する。

*2:今作った造語。参照先オブジェクトの生存期間が終了しており既に無効値となってるポインタ型(T*)変数や参照型(T&)変数は、一般にダングリング・ポインタ(dangling pointer)やダングリング参照(dangling reference)と呼ばれる。wikipedia:en:Dangling_pointer