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
- std::string_view accepting temporaries: good idea or horrible pitfall?
- C++17 - Avoid Copying with std::string_view - ModernesCpp.com
- cppreference basic_string_view
- range-based forと文字走査 - yohhoyの日記
- 文字列リテラルからのstd::string_view構築 - yohhoyの日記
*1:厳密には std::basic_string_view<charT, traits> クラステンプレート。簡単のため本文中ではクラスとして説明する。
*2:今作った造語。参照先オブジェクトの生存期間が終了しており既に無効値となってるポインタ型(T*)変数や参照型(T&)変数は、一般にダングリング・ポインタ(dangling pointer)やダングリング参照(dangling reference)と呼ばれる。wikipedia:en:Dangling_pointer