Если мы хотим передать строку или подстроку в библиотеку, которая не предоставляет поддержку класса std::string
Говоря упрощенно, такой конструкцией как раз и является класс std::string_view
Представим, что разрабатываем функции, которые ранее в качестве параметров принимали объекты типа std::string
std::string_view
для повышения совместимости с библиотеками, которые не знают об STL. Можно позволить другим библиотекам предоставлять string_view
для строк, содержащих полезные данные, скрытые за сложной реализацией типа string
, а затем применять их в нашем коде, совместимом с STL. Таким образом, класс string_view
ведет себя как минималистичный и полезный интерфейс, пригодный для использования многими библиотеками.Еще одной приятной особенностью является тот факт, что класс string_view
string
. Существует много возможностей грамотно использовать эту особенность. В данном разделе мы поработаем с классом string_view
, чтобы получить представление о его преимуществах и недостатках. Кроме того, увидим, как можно скрыть пробелы в начале и конце строки путем адаптации строковых представлений, а не изменения или копирования самой строки. Этот метод позволяет избежать ненужного копирования или изменения данных.Как это делается
В этом примере мы реализуем функцию, которая работает с особенностями класса string_view
1. Сначала указываем заголовочные файлы и директивы using
#include
#include
using namespace std;
2. Реализуем функцию, которая принимает в качестве единственного аргумента объект типа string_view
void print(string_view v)
{
3. Прежде чем сделать что-то с входной строкой, удалим все пробелы из ее начала и конца. Мы будем изменять не строку, а ее
find_first_not_of
найдет первый символ строки, который не является пробелом (' '
), символом табуляции ('\t'
) или символом перехода на новую строку ('\n'
). С помощью функции remove_prefix
мы переместим внутренний указатель класса string_view
на первый символ, не являющийся пробелом. В том случае, если строка содержит только пробелы, функция find_ first_not_of
вернет значение npos
, которое равно size_type(-1)
. Поскольку size_type
— беззнаковая переменная, мы получим очень большое число. Поэтому выберем меньшее число из полученных: words_begin или размер строкового представления: const auto words_begin (v.find_first_not_of(" \t\n"));
v.remove_prefix(min(words_begin, v.size()));
4. То же самое сделаем с пробелами в конце строки. Функция remove_suffix
const auto words_end (v.find_last_not_of(" \t\n"));
if (words_end != string_view::npos) {
v.remove_suffix(v.size() - words_end - 1);
}
5. Теперь можно вывести на экран строковое представление и его длину:
cout << "length: " << v.length()
<< " [" << v << "]\n";
}
6. В функции main
print
, передав ей разные типы аргументов. Сначала передадим ей во время выполнения строку char*
из указателя argv
. Во время выполнения программы он будет содержать имя нашего исполняемого файла. Затем передадим ей пустой объект string_view
. Далее передадим ей символьную строку, созданную в стиле С, а также строку, образованную с помощью литерала ""sv
, который динамически создаст объект типа string_view
. И наконец, передадим ей объект класса std::string
. Положительный момент заключается в следующем: ни один из данных аргументов не изменяется и не копируется, чтобы вызвать функцию print
. Не происходит выделения памяти в куче. Для большого количества строк и/или для длинных строк это очень эффективно.