#новичкам
Спасибо, ₿ Satoshic, за любезно предоставленный примерчик в рамках рубрики #ЧЗХ.
Посмотрите на этот код и скажите, что выведется на экран:
std::string_view crop_string_view(std::string_view str_view)
{
return std::string_view{str_view.begin() + 5};
}
int main()
{
const char* str = "some super mega long string";
std::string_view str_view = {str, 10};
std::cout << crop_string_view(str_view);
}
Складывается довольно уверенное ощущение, что мы берем первые 10 символов строки str и после этого отрезаем от этой подстроки первые 5 символов. И в итоге выведется "super".
Однако ваш компилятор думает иначе и выведется на самом деле вот что:
super mega long stringЧЗХ? str_view же содержит обезанную строку! Откуда там изначальная последовательность символов?
Дело в том, что str_view конечно не содержит никакую строку. Этот объект грубо говоря лишь ссылается на оригинальную строку с ограничениями на длину, которую мы задали в конструкторе.
И конечно вполне естественно на первый взгляд подумать, что
std::string_view{str_view.begin() + 5} здесь обрезается сама подстрока. Но это не так.Конструктор string_view от одного аргумента формирует вьюху от переданного итератора на начало строки и идет дальше прям до символа конца строки. str_view.begin() и str.begin() ничем не отличаются, это фактически тот же самый указатель на начало супер длинной строки. Поэтому и остановится конструктор в конце этой строки и на консоль выведется "super mega long string".
Поэтому если вы создаете std::string_view не от строкового литерала, то указывайте в конструкторе либо длину, либо итератор на конец последовательности.
Specify your boundaries. Stay cool.
#cpp17