Я просто столкнулся с некоторым недоразумением:
по крайней мере, в реализации libc ++ std :: эксперимент :: строка_view имеет следующую сжатую реализацию:
template <class _CharT, class _Traits....>
class basic_string_view {
public:
typedef _CharT value_type;
...
template <class _Allocator>
basic_string_view(const basic_string<_CharT, _Traits, _Allocator>& str):
__data(str.data()), __size(str.size())
{
}
private:
const value_type* __data;
size_type __size;
};
Означает ли эта реализация, что если мы передадим выражение rvalue в этот конструктор, мы получим неопределенное поведение при использовании __data после построения?
Вот так. string_view
является не владеющим оболочкой со ссылочной семантикой, которая должна использоваться только в том случае, если указанная строка переживает использование представления.
Типичный случай использования в параметрах функции, где фактическая строка живет в течение всего времени вызова функции, а тело функции никогда не сохраняет представление, а только читает Это:
void foo(std::experimental::string_view message) // pass by value
{
std::cout << "You said, '" << message << "'.\n";
}
Использование:
foo("Hello"); // OK, string literal has static storage
foo(s); // OK, s is alive
foo(s.substr(1)); // OK, temporary lives until end of full-expression
Мораль такова: если вам нужна строка только для продолжительности тела функции, дайте функции string_view
параметр, и он может равномерно связываться с любым видом аргумента stringoid. Вам не нужен шаблон функции, копирование string_view
s дешево, и вы получаете несколько аккуратных операций с подстрокой бесплатно. В отличие от никогда не хранить string_view
, но всегда хранитеstring
:
struct X
{
X(std::experimental::string_view s) : s_(s) {}
std::string s_; // NEVER have a string_view class member!
};