Rvalue для параметра std::string

Какая на практике разница между LVALUE и RVALUE в следующем коде, когда я передаю текст? Я имею в виду, что в этом конкретном случае строки (где строка является строковым литералом) есть ли какая-либо польза от использования RVALUE (&&)?

void write_Lvalue(const std::string &text) {
    //...
}

void write_Rvalue(const std::string &&text) {
    //...
}

int main() {
    write_Lvalue("writing the Lvalue");
    write_Rvalue("writing the Rvalue");
}

FWIW const std::string &&text не следует использовать. Вы побеждаете цель ссылки rvalue, делая то, на что она ссылается const. Если это const, его нельзя переместить, так как это операция мутирования.

NathanOliver 10.04.2019 21:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
1
2 776
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В этом случае никакой выгоды. write_Rvalue будет принимать только rvalue. и write_Lvalue будет принимать только lvalue.

Когда вы передаете строковый литерал, временный std::string будет создан из строкового литерала. Вариант rvalue уже может привязываться к этому, потому что вы уже передаете временное, а вариант lvalue может привязываться к временному, потому что это const.

Это, например, не будет компилироваться:

void write_Lvalue(const std::string &text) {
    //...
}

void write_Rvalue(const std::string &&text) {
    //...
}

int main() {
    std::string a = "hello";
    write_Rvalue(a);
}

потому что мы пытаемся передать lvalue a функции, принимающей только rvalue.

Преимущество, которое можно получить с помощью типов rvalue, заключается в том, что их можно перемещать. Есть отличный пост о том, почему двигаться можно быстрее здесь.

Создание вашего rvalue const побеждает его цель, как сказано в комментариях, потому что его больше нельзя переместить.

Ответ принят как подходящий

Во-первых, постоянные ссылки на 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, как показано выше.

Изменяемые ссылки lvalue также не работают с const lvalue и довольно грубы для пользователей (которые должны предполагать, что их переменная может быть изменена функцией).

Toby Speight 11.04.2019 18:07

Другие вопросы по теме

Похожие вопросы

Использование необработанного идентификатора внутри цикла switch-case для разбора CSV-файлов
Фатальная ошибка: auc_.cpp:2:10: фатальная ошибка: omp.h: Нет такого файла или каталога
Как отсортировать QList QGraphicsitem по координате x или координате y?
Не может быть явно специализирован в Visual Studio 2017
Как заставить пользовательский пустой конструктор по умолчанию вести себя как пустой конструктор, определенный компилятором
Как можно восстановить аргумент шаблона, отличный от имени типа, из каждого типа в вариативном пакете классов шаблонов?
В чем разница между двумя типами определяющих конструкторов? первый использует ":", а второй определяет его в фигурных скобках, как функции
Когда переходить на копирование/ссылку?
Имитация цветового стиля на основе QApplication::palette()
Как реализовать слабую ссылку на объект в конструкторе с помощью boost::weak_ptr?