Почему декларация sv2
плохая
За [basic.string.literals] / 1 :
string operator""s(const char* str, size_t len);
Возвращает: string{str, len}
.
В "foo"s
строковый литерал "foo"
используется для инициализации временного std::string
.Символы копируются в базовый массив временного std::string
.std::string_view
- это не принадлежащий вид, а sv2
указывает на базовый массив временного std::string
.После уничтожения временного std::string
, sv2
продолжает указывать на базовый массив (срок действия которого истек), и попытка вывести sv2
приводит к неопределенному поведению.
Почему объявление sv3
хорошо
За [string.view.literals] / 1 :
constexpr string_view operator""sv(const char* str, size_t len) noexcept;
Возвращает: string_view{str, len}
.
Следовательно, объявление sv3
эквивалентно: 1
std::string_view sv3{"baz", 3};
sv3
непосредственно указывает на строковый литерал "baz"
.Строковый литерал имеет статическую длительность хранения и не имеет срока действия.
1 Здесь есть некоторая тонкость.Копия elision может или может не применяться здесь.Поскольку string_view
s не являются владельцами, при копировании string_view
s не появляются новые временные строки.Следовательно, независимо от того, должна ли быть сделана копия, состояние sv3
остается одним и тем же.