Тип std:string_view

Последнее обновление: 07.03.2023

Если параметр представляет тип std::string, то мы можем передавать такому параметру как объект std::string, так и строковый литерал. Например:

#include <iostream>
 
void print(const std::string&);
int main()
{
    std::string message{"hello"};
    print(message);         // можем передать std::string
    print("Hello Work");    // можем передать строковый литерал
}

void print(const std::string& text)
{
    std::cout << text << std::endl;
}

Здесь строка передается по ссылке, что позволяет избежать ненужного копирования символов. А модификатор const защищает строку от изменения. Однако несмотря на то, что строка передается по ссылке, когда параметру передаем строковый литерал, то в памяти в процессе преобразования строкового литерала к типу std::string все равно будет идти копирование символов и соответственно дополнительные выделения памяти, что отрицательно влияет на производительность.

Тип std::string_view призван решить данную проблему. Он определен в модуле <string_view> и действует аналогично const std::string с одним исключением - string_view не копирует символы строкового объекта вне зависимости, что он представляет - тип std::string, строковый литерал или символьный масссив. Поэтому в качестве типа параметра оптимальнее использовать std::string_view, а не константную ссылку const std::string&. При этом не важно, что параметр может передаваться по значению, а не по ссылке - копирование символов все равно не будет происходить. В своей внутренней реализации std::string_view лишь копирует длину строки и указатель на последовательность символов.

Однако стоит отметить, что работа с типом string_views подразумевает, что символы строки не будут изменяться, поскольку тип string_views в своей внутренней реализации представляет константу вне зависимости от того, применяется ли к параметру модификатор const.

Изменим выше определенную программу, применив тип std::string_view:

#include <iostream>
#include <string>
#include <string_view>
 
void print(std::string_view);
int main()
{
    std::string message{"hello"};
    print(message);         // можем передать std::string
    print("Hello Work");    // можем передать строковый литерал
}

void print(std::string_view text)
{
    std::cout << text << std::endl;
}

В остальном, тип std::string_view реализует большинство тех же функций, что и тип std::string. Например, найдем в строке, которая представляет string_view, количество слов:

#include <iostream>
#include <vector>
#include <string_view>
 
std::vector<std::string_view> get_words(std::string_view);

int main()
{
    std::string text = " An apple a day keeps the doctor away."; // Исходный текст

    std::vector<std::string_view> words = get_words(text);

    // выводим количество слов
    std::cout << "\nText contains " << words.size() << " words:" << std::endl;
    // выводим все слова на консоль
    for (const auto& word : words)
    {
        std::cout << word << std::endl;
    }
}

std::vector<std::string_view> get_words(std::string_view text)
{
    const std::string_view separators{ " ,;:.\"!?'*\n" };
    std::vector<std::string_view> words; // вектор для хранения слов
    size_t start { text.find_first_not_of(separators) }; // начальный индекс первого слова
    while (start != std::string_view::npos) // проходим, пока в строке не окажется других символов, кроме separators
    {
        size_t end = text.find_first_of(separators, start + 1); // находим, где кончается слово
        if (end == std::string_view::npos) // если НЕ найден ни один из символов-разделителей
            end = text.length();        // устанавливаем переменную end на конец текста
        words.push_back(text.substr(start, end - start)); // добавляем в вектор слово
        start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start
    }
    return words;
}

По сути здесь реализована та же программа по подсчету слов, что и в прошлой статье, только в качестве текста передается строка типа std::string_view. И для выделения слов вызываем ряд функций типа, которые эквиваленты соответствующим функциям типа std::string: find_first_not_of(), find_first_of(), length().

Стоит отметить, что для работы со строками Unicode также имеются свои типы: std::wstring_view, std::u8string_view, std::u16string_view и std::u32string_view. Работа с этими типами будет аналогична работе с std::string_view.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850