yohhoyの日記

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

std::string_viewでは値渡しを利用する

C++1z(C++17)標準ライブラリ提供のstd::string_view*1 を関数パラメータ型で利用する場合、原則として値渡し(pass-by-value)スタイルとすること。

C++14以前でconst string&としていた関数パラメータ型は、ほとんどのケースでstring_viewへと単純置換できる。なお関数プロトタイプでconst string_viewとしてもパラメータ型のトップレベルconst修飾は無視されるため*2、const修飾は関数利用者へは影響しない。string_view型はもともと “読取専用の文字列ビュー” として設計されており、関数実装側にとってもconst修飾のメリットはほぼ無い。

// C++1z(C++17)
#include <string_view>

// C++14以前
// void process(const std::string& s);  // 文字列のconst参照渡し

// C++1z以降
void process(std::string_view sv);  // 文字列ビューの値渡し(pass-by-value)

std::string str = "string";
process(str);  // OK: string→string_viewへ暗黙変換

std::string long_str = /* 長~い文字列 */;
std::size_t pos = /*開始位置*/, count = /*文字数*/;

process(long_str.substr(pos, count));  // OK: 一時オブジェクトが生成されるため非効率
// string::substrメンバ関数呼び出し/戻り値型string

process(std::strig_view{long_str}.substr(pos, count));  // OK: 動的メモリ確保行われず効率的
// string_view::substrメンバ関数呼び出し/戻り値型string_view

(PDF)P0254R2 Integrating std::string_view and std::stringより一部引用(下線部は強調)。

Rationale
string_view as a basic vocabulary type leads to additional efficiencies.

Because it does not own the underlying data, a string_view is cheap to construct and to copy. The guidance that we give is that these should be passed by value. When there are no lifetime issues (and where null-termination is not an issue), string_view is a superior vocabulary type than string, and the standard should prefer it.

(snip)

Creating a string_view from a string is cheap, hence the implicit conversion. Creating a string from a string_view is not cheap, so it should be explicit.

関連URL

*1:厳密には std::basic_string_view<charT, traits> クラステンプレートとして提供される。

*2:C++14 8.3.5/p5: "After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type."