Saltar a contenido

Última actualización:2026-10-12

C++17 std::string_view

0.Problema

string_view apareció a partir de C++17; en realidad no es más que el slice de leveldb, y su propósito es evitar las copias de memoria y conseguir un substr eficiente.

Sin embargo, también introduce problemas de punteros y referencias: como string_view no posee la propiedad del contenido al que apunta, en comparación con Rust se trata solo de un préstamo; si el objeto que posee el contenido se libera antes de tiempo, aparece el problema de la referencia colgante. Rust analiza en tiempo de compilación el ciclo de vida de las variables, garantizando que los recursos tomados en préstamo no se liberen mientras se usan. C++, en cambio, no realiza esta comprobación y hay que garantizarla manualmente.

1.Implementación interna

string_view es un tipo basic_string_view; puede verse que _Traits usa por defecto char_traits, algo muy importante: varias de las funciones posteriores ejecutan sus operaciones centrales mediante funciones miembro de char_traits.

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

typedef basic_string_view<char>     string_view;

Miembros internos de basic_string_view:

private:
    const   value_type* __data;
    size_type           __size;

La construcción es compatible con string y 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);

Soporte de 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;

Otras funciones esenciales:

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

A partir de C++20 se soportan starts_with, ends_with y contains; estas tres ya estaban soportadas desde el principio en el slice de 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.Trampas de uso

2.1 \0

string_view no se ocupa de \0; lo que tiene en cuenta es el número real de caracteres.

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

Salida: s: 8 "abcdef"

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

Aquí lo que se espera mostrar es hello, pero se muestra h.

2.2 Ciclo de vida

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

En este ejemplo, cuando s sale del ámbito, string_view se convierte en una referencia colgante.

Ciclo de vida

std::string_view no posee el almacenamiento de caracteres subyacente: asegúrate de que el ciclo de vida del objeto referenciado cubra todo el periodo de uso.

Temas relacionados

Comentarios