Если параметр представляет тип 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
.