Во-первых, постоянные ссылки на rvalue не очень полезны, так как вы не можете их перемещать. Движущееся значение требует изменяемых ссылок для работы.
Давайте возьмем ваш исправленный пример:
void write_lvalue(std::string const& text) {
//...
}
void write_rvalue(std::string&& text) {
//...
}
int main() {
write_lvalue("writing the Lvalue");
write_rvalue("writing the Rvalue");
}
В этом случае два полностью эквивалентны . В этих двух случаях компилятор должен создать строку и отправить ее по ссылке:
int main() {
// equivalent, string created
// and sent by reference (const& bind to temporaries)
write_lvalue(std::string{"writing the Lvalue"});
// equivalent, string created
// and sent by reference (&& bind to temporaries)
write_rvalue(std::string{"writing the Rvalue"});
}
Итак, почему есть функция, которая принимает rvalue ссылки?
Это зависит от того, что вы делаете со строкой. Изменяемая ссылка может быть перемещена из:
std::string global_string;
void write_lvalue(std::string const& text) {
// copy, might cause allocation
global_string = text;
}
void write_rvalue(std::string&& text) {
// move, no allocation, yay!
global_string = std::move(text);
}
Так зачем вообще использовать ссылку на rvalue? Почему бы не использовать изменяемую ссылку lvalue?
Это потому, что изменяемые ссылки lvalue не могут быть привязаны к временным файлам:
void write_lvalue_mut(std::string& text) {
// move, no allocation... yay?
global_string = std::move(text);
}
int main() {
std::string s = /* ... */;
write_lvalue_mut(std::move(s)); // fails
write_lvalue_mut("some text"); // also fails
}
Но изменяемая ссылка на rvalue может быть связана с rvalue, как показано выше.