Последнее обновление:2026-10-12
std::string_view в C++17¶
0.Проблема¶
string_view появился после C++17 и, по сути, является аналогом slice из leveldb; его цель — избежать копирования памяти и обеспечить эффективный 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
- ...
Начиная с C++20 поддерживаются starts_with, ends_with и contains; в slice из leveldb эти три функции поддерживались с самого начала.
Строковый литерал string_view для char*:
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 не владеет нижележащим хранилищем символов — обязательно убедитесь, что время жизни объекта, на который ссылаются, охватывает весь период использования.
Похожие темы¶
- Атрибут [[nodiscard]] в C++17 | C++那些事
- PMR-ресурсы памяти в C++17 | C++那些事
- Семнадцать расширенных возможностей C++17 | C++那些事
- Выведение аргументов шаблона класса CTAD в C++17 | C++那些事
- C++17 optional_ref | C++那些事
- std::variant в C++17 | C++那些事
- Структурированные привязки в C++17 | C++那些事
- Выведение auto в шаблонах C++17 | C++那些事
- Шаблоны переменных в C++17 | C++那些事