QStringView is typically used in high-performance code where creating actual QString objects would be slow due to the memory allocation involved. I optimized QStringView so that it is as performant as handling a (const QChar*, size_t) manually. I even went to the length of having member function calls hand off inline to free functions, passing *this by value. All this is to avoid forcing QStringView objects onto the stack, or, more generally, into memory.
In virtually all C++ compilers, a QStringView object is represented as a pair of CPU registers, and many C++ ABIs (sadly, excluding Windows) support passing such types in CPU registers to functions. If you wrote the member function naïvely, with an implicit this parameter as the address of the object, calling such a function out-of-line would force the compiler to allocate a QStringView object on the stack to be able to pass its address as the first argument of the member function.
There's a second argument for pass-by-value: there are less aliasing problems. As a reference type, QStringView exhibits that problem anyway, but consider std::complex: Take
std::complex &operator*=(std::complex &lhs, const std::complex &rhs);
(template args omitted for brevity). This can be called like this:
std::complex c = 3 + 4i;
c *= c;
If you naïvely implement operator*= as if it was a mathematical function:
auto r = real(), i = imag();
m_real = r * other.real() - i * other.imag();
m_imag = r * other.imag() + i * other.real();
you would have clobbered other.real() after the first line, thus calculating a wrong result (yes, people do write this code in production). Passing the rhs by value makes the problem go away.