Ir para o conteúdo

Última atualização:2026-10-12

C++17 std::string_view

0.Problema

string_view surgiu a partir do C++17 e, na prática, é o slice do leveldb; seu objetivo é evitar cópias de memória e oferecer um substr eficiente.

Porém, isso também introduz problemas de ponteiros e referências: como o string_view não possui a propriedade do conteúdo apontado, comparado com o Rust ele é apenas um empréstimo; se o objeto que possui o conteúdo for liberado antecipadamente, surgirá o problema de referência pendente (dangling). O Rust analisa em tempo de compilação o tempo de vida das variáveis, garantindo que os recursos emprestados não sejam liberados enquanto estão em uso. O C++, por sua vez, não faz essa verificação: é preciso garanti-la manualmente.

1.Implementação interna

string_view é um tipo basic_string_view; pode-se ver que _Traits usa o char_traits padrão, o que é muito importante, pois diversas funções adiante usam funções-membro de char_traits para executar as operações centrais.

template<class _CharT, class _Traits = char_traits<_CharT> >
    class _LIBCPP_TEMPLATE_VIS basic_string_view;

typedef basic_string_view<char>     string_view;

Membros internos do basic_string_view:

private:
    const   value_type* __data;
    size_type           __size;

Construtores compatíveis com string e 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);

Suporte a iteradores:

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;

Outras funções centrais:

  • substr
  • remove_prefix
  • compare
  • find
  • ...

A partir do C++20, há suporte a starts_with, ends_with e contains; esses três já eram suportados desde o início no slice do leveldb.

Literal string_view para 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.Armadilhas de uso

2.1 \0

O string_view não se preocupa com o \0; ele se importa com a quantidade real de caracteres.

std::string_view s = "abc\0\0def"sv;
std::cout << "s: " << s.size() << " \"" << s << "\"\n";

Saída: s: 8 "abcdef"

std::string_view str{"hello", 1};
std::cout << str.data() << std::endl; // 输出 hello,而不是h

Aqui o esperado seria imprimir hello, mas foi impresso apenas h.

2.2 Tempo de vida

string_view foo() {
    std::string s{"hello world"};
    return string_view{s};
}

Nesse exemplo, s saiu do escopo e o string_view tornou-se uma referência pendente.

Tempo de vida

O std::string_view não possui o armazenamento de caracteres subjacente; certifique-se de que o tempo de vida do objeto referenciado cubra todo o período de uso.

Tópicos relacionados

Comentários