最終更新:2026-10-12
C++17 std::string_view¶
0.問題¶
string_viewはC++17以降で登場したもので、実体はleveldbにおけるsliceです。その目的は、メモリコピーの解消と効率的なsubstrにあります。
しかし、同時にポインタと参照の問題も持ち込まれました。string_viewは指す内容の所有権を持たないため、Rustと比べると、いわば借用にすぎません。内容を所有するオブジェクトが先に解放されると、ダングリング参照の問題が発生します。Rustのようにコンパイル時に変数のライフタイムを解析し、借用したリソースが使用中に解放されないことを保証しますが、C++にはそのような検査がないため、人手で保証する必要があります。
1.内部実装¶
string_viewはbasic_string_viewという型で、_Traitsにはデフォルトのchar_traitsが採用されていることがわかります。これは重要で、後述のいくつかの関数は、char_traitsのメンバ関数を使って核心的な操作を実行します。
template<class _CharT, class _Traits = char_traits<_CharT> >
class _LIBCPP_TEMPLATE_VIS basic_string_view;
typedef basic_string_view<char> string_view;
basic_string_viewの内部メンバ:
コンストラクタはstringとconst char*に対応しています
constexpr basic_string_view() noexcept;
constexpr basic_string_view(const basic_string_view&) noexcept = default;
basic_string_view& operator=(const basic_string_view&) noexcept = default;
template<class Allocator>
constexpr basic_string_view(const charT* str);
constexpr basic_string_view(const charT* str, size_type len);
イテレータサポート:
constexpr const_iterator begin() const noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr const_iterator cend() const noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
その他の主要関数:
- substr
- remove_prefix
- compare
- find
- ...
starts_with、ends_with、containsはC++20からサポートされます。この3つは、leveldbのsliceでは当初からサポートされていました。
char*のstring_viewリテラル:
constexpr basic_string_view<char> operator "" sv( const char *str, size_t len ) noexcept;
constexpr basic_string_view<wchar_t> operator "" sv( const wchar_t *str, size_t len ) noexcept;
constexpr basic_string_view<char16_t> operator "" sv( const char16_t *str, size_t len ) noexcept;
constexpr basic_string_view<char32_t> operator "" sv( const char32_t *str, size_t len ) noexcept;
2.使用上の罠¶
2.1 \0¶
string_viewは\0を考慮せず、実際の文字数のほうを気にします。
出力:s: 8 "abcdef"
ここではhelloと出力されることを期待していますが、実際に出力されるのはhです。
2.2 ライフタイム¶
この例では、sがスコープを抜けると、string_viewはダングリング参照になってしまいます。
ライフタイム
std::string_view は基となる文字列ストレージを所有しません。参照先オブジェクトのライフタイムが使用期間全体をカバーするように、必ず保証してください。
関連トピック¶
- C++17 [[nodiscard]] 属性 | C++那些事
- C++17 PMR メモリリソース | C++那些事
- C++17 17の高度な機能 | C++那些事
- C++17 クラステンプレートのテンプレート引数推論 CTAD | C++那些事
- C++17 optional_ref | C++那些事
- C++17 std::variant | C++那些事
- C++17 構造化束縛 | C++那些事
- C++17 テンプレート auto 推論 | C++那些事
- C++17 変数テンプレート | C++那些事